1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163 |
- //===--- ParseExpr.cpp - Expression Parsing -------------------------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- ///
- /// \file
- /// Provides the Expression parsing implementation.
- ///
- /// Expressions in C99 basically consist of a bunch of binary operators with
- /// unary operators and other random stuff at the leaves.
- ///
- /// In the C99 grammar, these unary operators bind tightest and are represented
- /// as the 'cast-expression' production. Everything else is either a binary
- /// operator (e.g. '/') or a ternary operator ("?:"). The unary leaves are
- /// handled by ParseCastExpression, the higher level pieces are handled by
- /// ParseBinaryExpression.
- ///
- //===----------------------------------------------------------------------===//
- #include "clang/Parse/Parser.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/Basic/PrettyStackTrace.h"
- #include "clang/Parse/RAIIObjectsForParser.h"
- #include "clang/Sema/DeclSpec.h"
- #include "clang/Sema/ParsedTemplate.h"
- #include "clang/Sema/Scope.h"
- #include "clang/Sema/TypoCorrection.h"
- #include "llvm/ADT/SmallVector.h"
- using namespace clang;
- /// Simple precedence-based parser for binary/ternary operators.
- ///
- /// Note: we diverge from the C99 grammar when parsing the assignment-expression
- /// production. C99 specifies that the LHS of an assignment operator should be
- /// parsed as a unary-expression, but consistency dictates that it be a
- /// conditional-expession. In practice, the important thing here is that the
- /// LHS of an assignment has to be an l-value, which productions between
- /// unary-expression and conditional-expression don't produce. Because we want
- /// consistency, we parse the LHS as a conditional-expression, then check for
- /// l-value-ness in semantic analysis stages.
- ///
- /// \verbatim
- /// pm-expression: [C++ 5.5]
- /// cast-expression
- /// pm-expression '.*' cast-expression
- /// pm-expression '->*' cast-expression
- ///
- /// multiplicative-expression: [C99 6.5.5]
- /// Note: in C++, apply pm-expression instead of cast-expression
- /// cast-expression
- /// multiplicative-expression '*' cast-expression
- /// multiplicative-expression '/' cast-expression
- /// multiplicative-expression '%' cast-expression
- ///
- /// additive-expression: [C99 6.5.6]
- /// multiplicative-expression
- /// additive-expression '+' multiplicative-expression
- /// additive-expression '-' multiplicative-expression
- ///
- /// shift-expression: [C99 6.5.7]
- /// additive-expression
- /// shift-expression '<<' additive-expression
- /// shift-expression '>>' additive-expression
- ///
- /// compare-expression: [C++20 expr.spaceship]
- /// shift-expression
- /// compare-expression '<=>' shift-expression
- ///
- /// relational-expression: [C99 6.5.8]
- /// compare-expression
- /// relational-expression '<' compare-expression
- /// relational-expression '>' compare-expression
- /// relational-expression '<=' compare-expression
- /// relational-expression '>=' compare-expression
- ///
- /// equality-expression: [C99 6.5.9]
- /// relational-expression
- /// equality-expression '==' relational-expression
- /// equality-expression '!=' relational-expression
- ///
- /// AND-expression: [C99 6.5.10]
- /// equality-expression
- /// AND-expression '&' equality-expression
- ///
- /// exclusive-OR-expression: [C99 6.5.11]
- /// AND-expression
- /// exclusive-OR-expression '^' AND-expression
- ///
- /// inclusive-OR-expression: [C99 6.5.12]
- /// exclusive-OR-expression
- /// inclusive-OR-expression '|' exclusive-OR-expression
- ///
- /// logical-AND-expression: [C99 6.5.13]
- /// inclusive-OR-expression
- /// logical-AND-expression '&&' inclusive-OR-expression
- ///
- /// logical-OR-expression: [C99 6.5.14]
- /// logical-AND-expression
- /// logical-OR-expression '||' logical-AND-expression
- ///
- /// conditional-expression: [C99 6.5.15]
- /// logical-OR-expression
- /// logical-OR-expression '?' expression ':' conditional-expression
- /// [GNU] logical-OR-expression '?' ':' conditional-expression
- /// [C++] the third operand is an assignment-expression
- ///
- /// assignment-expression: [C99 6.5.16]
- /// conditional-expression
- /// unary-expression assignment-operator assignment-expression
- /// [C++] throw-expression [C++ 15]
- ///
- /// assignment-operator: one of
- /// = *= /= %= += -= <<= >>= &= ^= |=
- ///
- /// expression: [C99 6.5.17]
- /// assignment-expression ...[opt]
- /// expression ',' assignment-expression ...[opt]
- /// \endverbatim
- ExprResult Parser::ParseExpression(TypeCastState isTypeCast) {
- ExprResult LHS(ParseAssignmentExpression(isTypeCast));
- return ParseRHSOfBinaryExpression(LHS, prec::Comma);
- }
- /// This routine is called when the '@' is seen and consumed.
- /// Current token is an Identifier and is not a 'try'. This
- /// routine is necessary to disambiguate \@try-statement from,
- /// for example, \@encode-expression.
- ///
- ExprResult
- Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) {
- ExprResult LHS(ParseObjCAtExpression(AtLoc));
- return ParseRHSOfBinaryExpression(LHS, prec::Comma);
- }
- /// This routine is called when a leading '__extension__' is seen and
- /// consumed. This is necessary because the token gets consumed in the
- /// process of disambiguating between an expression and a declaration.
- ExprResult
- Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
- ExprResult LHS(true);
- {
- // Silence extension warnings in the sub-expression
- ExtensionRAIIObject O(Diags);
- LHS = ParseCastExpression(false);
- }
- if (!LHS.isInvalid())
- LHS = Actions.ActOnUnaryOp(getCurScope(), ExtLoc, tok::kw___extension__,
- LHS.get());
- return ParseRHSOfBinaryExpression(LHS, prec::Comma);
- }
- /// Parse an expr that doesn't include (top-level) commas.
- ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) {
- if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
- cutOffParsing();
- return ExprError();
- }
- if (Tok.is(tok::kw_throw))
- return ParseThrowExpression();
- if (Tok.is(tok::kw_co_yield))
- return ParseCoyieldExpression();
- ExprResult LHS = ParseCastExpression(/*isUnaryExpression=*/false,
- /*isAddressOfOperand=*/false,
- isTypeCast);
- return ParseRHSOfBinaryExpression(LHS, prec::Assignment);
- }
- /// Parse an assignment expression where part of an Objective-C message
- /// send has already been parsed.
- ///
- /// In this case \p LBracLoc indicates the location of the '[' of the message
- /// send, and either \p ReceiverName or \p ReceiverExpr is non-null indicating
- /// the receiver of the message.
- ///
- /// Since this handles full assignment-expression's, it handles postfix
- /// expressions and other binary operators for these expressions as well.
- ExprResult
- Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
- SourceLocation SuperLoc,
- ParsedType ReceiverType,
- Expr *ReceiverExpr) {
- ExprResult R
- = ParseObjCMessageExpressionBody(LBracLoc, SuperLoc,
- ReceiverType, ReceiverExpr);
- R = ParsePostfixExpressionSuffix(R);
- return ParseRHSOfBinaryExpression(R, prec::Assignment);
- }
- ExprResult
- Parser::ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast) {
- assert(Actions.ExprEvalContexts.back().Context ==
- Sema::ExpressionEvaluationContext::ConstantEvaluated &&
- "Call this function only if your ExpressionEvaluationContext is "
- "already ConstantEvaluated");
- ExprResult LHS(ParseCastExpression(false, false, isTypeCast));
- ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
- return Actions.ActOnConstantExpression(Res);
- }
- ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) {
- // 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);
- }
- ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) {
- EnterExpressionEvaluationContext ConstantEvaluated(
- Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
- ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
- ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
- return Actions.ActOnCaseExpr(CaseLoc, Res);
- }
- /// Parse a constraint-expression.
- ///
- /// \verbatim
- /// constraint-expression: [Concepts TS temp.constr.decl p1]
- /// logical-or-expression
- /// \endverbatim
- ExprResult Parser::ParseConstraintExpression() {
- // FIXME: this may erroneously consume a function-body as the braced
- // initializer list of a compound literal
- //
- // FIXME: this may erroneously consume a parenthesized rvalue reference
- // declarator as a parenthesized address-of-label expression
- ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false));
- ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
- return Res;
- }
- bool Parser::isNotExpressionStart() {
- tok::TokenKind K = Tok.getKind();
- if (K == tok::l_brace || K == tok::r_brace ||
- K == tok::kw_for || K == tok::kw_while ||
- K == tok::kw_if || K == tok::kw_else ||
- K == tok::kw_goto || K == tok::kw_try)
- return true;
- // If this is a decl-specifier, we can't be at the start of an expression.
- return isKnownToBeDeclarationSpecifier();
- }
- bool Parser::isFoldOperator(prec::Level Level) const {
- return Level > prec::Unknown && Level != prec::Conditional &&
- Level != prec::Spaceship;
- }
- bool Parser::isFoldOperator(tok::TokenKind Kind) const {
- return isFoldOperator(getBinOpPrecedence(Kind, GreaterThanIsOperator, true));
- }
- /// Parse a binary expression that starts with \p LHS and has a
- /// precedence of at least \p MinPrec.
- ExprResult
- Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
- prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(),
- GreaterThanIsOperator,
- getLangOpts().CPlusPlus11);
- SourceLocation ColonLoc;
- while (1) {
- // If this token has a lower precedence than we are allowed to parse (e.g.
- // because we are called recursively, or because the token is not a binop),
- // then we are done!
- if (NextTokPrec < MinPrec)
- return LHS;
- // Consume the operator, saving the operator token for error reporting.
- Token OpToken = Tok;
- ConsumeToken();
- if (OpToken.is(tok::caretcaret)) {
- return ExprError(Diag(Tok, diag::err_opencl_logical_exclusive_or));
- }
- // If we're potentially in a template-id, we may now be able to determine
- // whether we're actually in one or not.
- if (OpToken.isOneOf(tok::comma, tok::greater, tok::greatergreater,
- tok::greatergreatergreater) &&
- checkPotentialAngleBracketDelimiter(OpToken))
- return ExprError();
- // Bail out when encountering a comma followed by a token which can't
- // possibly be the start of an expression. For instance:
- // int f() { return 1, }
- // We can't do this before consuming the comma, because
- // isNotExpressionStart() looks at the token stream.
- if (OpToken.is(tok::comma) && isNotExpressionStart()) {
- PP.EnterToken(Tok);
- Tok = OpToken;
- return LHS;
- }
- // If the next token is an ellipsis, then this is a fold-expression. Leave
- // it alone so we can handle it in the paren expression.
- if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) {
- // FIXME: We can't check this via lookahead before we consume the token
- // because that tickles a lexer bug.
- PP.EnterToken(Tok);
- Tok = OpToken;
- return LHS;
- }
- // In Objective-C++, alternative operator tokens can be used as keyword args
- // in message expressions. Unconsume the token so that it can reinterpreted
- // as an identifier in ParseObjCMessageExpressionBody. i.e., we support:
- // [foo meth:0 and:0];
- // [foo not_eq];
- if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus &&
- Tok.isOneOf(tok::colon, tok::r_square) &&
- OpToken.getIdentifierInfo() != nullptr) {
- PP.EnterToken(Tok);
- Tok = OpToken;
- return LHS;
- }
- // Special case handling for the ternary operator.
- ExprResult TernaryMiddle(true);
- if (NextTokPrec == prec::Conditional) {
- if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
- // Parse a braced-init-list here for error recovery purposes.
- SourceLocation BraceLoc = Tok.getLocation();
- TernaryMiddle = ParseBraceInitializer();
- if (!TernaryMiddle.isInvalid()) {
- Diag(BraceLoc, diag::err_init_list_bin_op)
- << /*RHS*/ 1 << PP.getSpelling(OpToken)
- << Actions.getExprRange(TernaryMiddle.get());
- TernaryMiddle = ExprError();
- }
- } else if (Tok.isNot(tok::colon)) {
- // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
- ColonProtectionRAIIObject X(*this);
- // Handle this production specially:
- // logical-OR-expression '?' expression ':' conditional-expression
- // In particular, the RHS of the '?' is 'expression', not
- // 'logical-OR-expression' as we might expect.
- TernaryMiddle = ParseExpression();
- } else {
- // Special case handling of "X ? Y : Z" where Y is empty:
- // logical-OR-expression '?' ':' conditional-expression [GNU]
- TernaryMiddle = nullptr;
- Diag(Tok, diag::ext_gnu_conditional_expr);
- }
- if (TernaryMiddle.isInvalid()) {
- Actions.CorrectDelayedTyposInExpr(LHS);
- LHS = ExprError();
- TernaryMiddle = nullptr;
- }
- if (!TryConsumeToken(tok::colon, ColonLoc)) {
- // Otherwise, we're missing a ':'. Assume that this was a typo that
- // the user forgot. If we're not in a macro expansion, we can suggest
- // a fixit hint. If there were two spaces before the current token,
- // suggest inserting the colon in between them, otherwise insert ": ".
- SourceLocation FILoc = Tok.getLocation();
- const char *FIText = ": ";
- const SourceManager &SM = PP.getSourceManager();
- if (FILoc.isFileID() || PP.isAtStartOfMacroExpansion(FILoc, &FILoc)) {
- assert(FILoc.isFileID());
- bool IsInvalid = false;
- const char *SourcePtr =
- SM.getCharacterData(FILoc.getLocWithOffset(-1), &IsInvalid);
- if (!IsInvalid && *SourcePtr == ' ') {
- SourcePtr =
- SM.getCharacterData(FILoc.getLocWithOffset(-2), &IsInvalid);
- if (!IsInvalid && *SourcePtr == ' ') {
- FILoc = FILoc.getLocWithOffset(-1);
- FIText = ":";
- }
- }
- }
- Diag(Tok, diag::err_expected)
- << tok::colon << FixItHint::CreateInsertion(FILoc, FIText);
- Diag(OpToken, diag::note_matching) << tok::question;
- ColonLoc = Tok.getLocation();
- }
- }
- // Code completion for the right-hand side of an assignment expression
- // goes through a special hook that takes the left-hand side into account.
- if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) {
- Actions.CodeCompleteAssignmentRHS(getCurScope(), LHS.get());
- cutOffParsing();
- return ExprError();
- }
- // Parse another leaf here for the RHS of the operator.
- // ParseCastExpression works here because all RHS expressions in C have it
- // as a prefix, at least. However, in C++, an assignment-expression could
- // be a throw-expression, which is not a valid cast-expression.
- // Therefore we need some special-casing here.
- // Also note that the third operand of the conditional operator is
- // an assignment-expression in C++, and in C++11, we can have a
- // braced-init-list on the RHS of an assignment. For better diagnostics,
- // parse as if we were allowed braced-init-lists everywhere, and check that
- // they only appear on the RHS of assignments later.
- ExprResult RHS;
- bool RHSIsInitList = false;
- if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
- RHS = ParseBraceInitializer();
- RHSIsInitList = true;
- } else if (getLangOpts().CPlusPlus && NextTokPrec <= prec::Conditional)
- RHS = ParseAssignmentExpression();
- else
- RHS = ParseCastExpression(false);
- if (RHS.isInvalid()) {
- // FIXME: Errors generated by the delayed typo correction should be
- // printed before errors from parsing the RHS, not after.
- Actions.CorrectDelayedTyposInExpr(LHS);
- if (TernaryMiddle.isUsable())
- TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle);
- LHS = ExprError();
- }
- // Remember the precedence of this operator and get the precedence of the
- // operator immediately to the right of the RHS.
- prec::Level ThisPrec = NextTokPrec;
- NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
- getLangOpts().CPlusPlus11);
- // Assignment and conditional expressions are right-associative.
- bool isRightAssoc = ThisPrec == prec::Conditional ||
- ThisPrec == prec::Assignment;
- // Get the precedence of the operator to the right of the RHS. If it binds
- // more tightly with RHS than we do, evaluate it completely first.
- if (ThisPrec < NextTokPrec ||
- (ThisPrec == NextTokPrec && isRightAssoc)) {
- if (!RHS.isInvalid() && RHSIsInitList) {
- Diag(Tok, diag::err_init_list_bin_op)
- << /*LHS*/0 << PP.getSpelling(Tok) << Actions.getExprRange(RHS.get());
- RHS = ExprError();
- }
- // If this is left-associative, only parse things on the RHS that bind
- // more tightly than the current operator. If it is left-associative, it
- // is okay, to bind exactly as tightly. For example, compile A=B=C=D as
- // A=(B=(C=D)), where each paren is a level of recursion here.
- // The function takes ownership of the RHS.
- RHS = ParseRHSOfBinaryExpression(RHS,
- static_cast<prec::Level>(ThisPrec + !isRightAssoc));
- RHSIsInitList = false;
- if (RHS.isInvalid()) {
- // FIXME: Errors generated by the delayed typo correction should be
- // printed before errors from ParseRHSOfBinaryExpression, not after.
- Actions.CorrectDelayedTyposInExpr(LHS);
- if (TernaryMiddle.isUsable())
- TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle);
- LHS = ExprError();
- }
- NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
- getLangOpts().CPlusPlus11);
- }
- if (!RHS.isInvalid() && RHSIsInitList) {
- if (ThisPrec == prec::Assignment) {
- Diag(OpToken, diag::warn_cxx98_compat_generalized_initializer_lists)
- << Actions.getExprRange(RHS.get());
- } else if (ColonLoc.isValid()) {
- Diag(ColonLoc, diag::err_init_list_bin_op)
- << /*RHS*/1 << ":"
- << Actions.getExprRange(RHS.get());
- LHS = ExprError();
- } else {
- Diag(OpToken, diag::err_init_list_bin_op)
- << /*RHS*/1 << PP.getSpelling(OpToken)
- << Actions.getExprRange(RHS.get());
- LHS = ExprError();
- }
- }
- ExprResult OrigLHS = LHS;
- if (!LHS.isInvalid()) {
- // Combine the LHS and RHS into the LHS (e.g. build AST).
- if (TernaryMiddle.isInvalid()) {
- // If we're using '>>' as an operator within a template
- // argument list (in C++98), suggest the addition of
- // parentheses so that the code remains well-formed in C++0x.
- if (!GreaterThanIsOperator && OpToken.is(tok::greatergreater))
- SuggestParentheses(OpToken.getLocation(),
- diag::warn_cxx11_right_shift_in_template_arg,
- SourceRange(Actions.getExprRange(LHS.get()).getBegin(),
- Actions.getExprRange(RHS.get()).getEnd()));
- LHS = Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(),
- OpToken.getKind(), LHS.get(), RHS.get());
- } else {
- LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
- LHS.get(), TernaryMiddle.get(),
- RHS.get());
- }
- // In this case, ActOnBinOp or ActOnConditionalOp performed the
- // CorrectDelayedTyposInExpr check.
- if (!getLangOpts().CPlusPlus)
- continue;
- }
- // Ensure potential typos aren't left undiagnosed.
- if (LHS.isInvalid()) {
- Actions.CorrectDelayedTyposInExpr(OrigLHS);
- Actions.CorrectDelayedTyposInExpr(TernaryMiddle);
- Actions.CorrectDelayedTyposInExpr(RHS);
- }
- }
- }
- /// Parse a cast-expression, or, if \p isUnaryExpression is true,
- /// parse a unary-expression.
- ///
- /// \p isAddressOfOperand exists because an id-expression that is the
- /// operand of address-of gets special treatment due to member pointers.
- ///
- ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
- bool isAddressOfOperand,
- TypeCastState isTypeCast,
- bool isVectorLiteral) {
- bool NotCastExpr;
- ExprResult Res = ParseCastExpression(isUnaryExpression,
- isAddressOfOperand,
- NotCastExpr,
- isTypeCast,
- isVectorLiteral);
- if (NotCastExpr)
- Diag(Tok, diag::err_expected_expression);
- return Res;
- }
- namespace {
- class CastExpressionIdValidator : public CorrectionCandidateCallback {
- public:
- CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes)
- : NextToken(Next), AllowNonTypes(AllowNonTypes) {
- WantTypeSpecifiers = WantFunctionLikeCasts = AllowTypes;
- }
- bool ValidateCandidate(const TypoCorrection &candidate) override {
- NamedDecl *ND = candidate.getCorrectionDecl();
- if (!ND)
- return candidate.isKeyword();
- if (isa<TypeDecl>(ND))
- return WantTypeSpecifiers;
- if (!AllowNonTypes || !CorrectionCandidateCallback::ValidateCandidate(candidate))
- return false;
- if (!NextToken.isOneOf(tok::equal, tok::arrow, tok::period))
- return true;
- for (auto *C : candidate) {
- NamedDecl *ND = C->getUnderlyingDecl();
- if (isa<ValueDecl>(ND) && !isa<FunctionDecl>(ND))
- return true;
- }
- return false;
- }
- private:
- Token NextToken;
- bool AllowNonTypes;
- };
- }
- /// Parse a cast-expression, or, if \pisUnaryExpression is true, parse
- /// a unary-expression.
- ///
- /// \p isAddressOfOperand exists because an id-expression that is the operand
- /// of address-of gets special treatment due to member pointers. NotCastExpr
- /// is set to true if the token is not the start of a cast-expression, and no
- /// diagnostic is emitted in this case and no tokens are consumed.
- ///
- /// \verbatim
- /// cast-expression: [C99 6.5.4]
- /// unary-expression
- /// '(' type-name ')' cast-expression
- ///
- /// unary-expression: [C99 6.5.3]
- /// postfix-expression
- /// '++' unary-expression
- /// '--' unary-expression
- /// [Coro] 'co_await' cast-expression
- /// unary-operator cast-expression
- /// 'sizeof' unary-expression
- /// 'sizeof' '(' type-name ')'
- /// [C++11] 'sizeof' '...' '(' identifier ')'
- /// [GNU] '__alignof' unary-expression
- /// [GNU] '__alignof' '(' type-name ')'
- /// [C11] '_Alignof' '(' type-name ')'
- /// [C++11] 'alignof' '(' type-id ')'
- /// [GNU] '&&' identifier
- /// [C++11] 'noexcept' '(' expression ')' [C++11 5.3.7]
- /// [C++] new-expression
- /// [C++] delete-expression
- ///
- /// unary-operator: one of
- /// '&' '*' '+' '-' '~' '!'
- /// [GNU] '__extension__' '__real' '__imag'
- ///
- /// primary-expression: [C99 6.5.1]
- /// [C99] identifier
- /// [C++] id-expression
- /// constant
- /// string-literal
- /// [C++] boolean-literal [C++ 2.13.5]
- /// [C++11] 'nullptr' [C++11 2.14.7]
- /// [C++11] user-defined-literal
- /// '(' expression ')'
- /// [C11] generic-selection
- /// '__func__' [C99 6.4.2.2]
- /// [GNU] '__FUNCTION__'
- /// [MS] '__FUNCDNAME__'
- /// [MS] 'L__FUNCTION__'
- /// [MS] '__FUNCSIG__'
- /// [MS] 'L__FUNCSIG__'
- /// [GNU] '__PRETTY_FUNCTION__'
- /// [GNU] '(' compound-statement ')'
- /// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
- /// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
- /// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
- /// assign-expr ')'
- /// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
- /// [GNU] '__null'
- /// [OBJC] '[' objc-message-expr ']'
- /// [OBJC] '\@selector' '(' objc-selector-arg ')'
- /// [OBJC] '\@protocol' '(' identifier ')'
- /// [OBJC] '\@encode' '(' type-name ')'
- /// [OBJC] objc-string-literal
- /// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
- /// [C++11] simple-type-specifier braced-init-list [C++11 5.2.3]
- /// [C++] typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
- /// [C++11] typename-specifier braced-init-list [C++11 5.2.3]
- /// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
- /// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
- /// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
- /// [C++] 'static_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
- /// [C++] 'typeid' '(' expression ')' [C++ 5.2p1]
- /// [C++] 'typeid' '(' type-id ')' [C++ 5.2p1]
- /// [C++] 'this' [C++ 9.3.2]
- /// [G++] unary-type-trait '(' type-id ')'
- /// [G++] binary-type-trait '(' type-id ',' type-id ')' [TODO]
- /// [EMBT] array-type-trait '(' type-id ',' integer ')'
- /// [clang] '^' block-literal
- ///
- /// constant: [C99 6.4.4]
- /// integer-constant
- /// floating-constant
- /// enumeration-constant -> identifier
- /// character-constant
- ///
- /// id-expression: [C++ 5.1]
- /// unqualified-id
- /// qualified-id
- ///
- /// unqualified-id: [C++ 5.1]
- /// identifier
- /// operator-function-id
- /// conversion-function-id
- /// '~' class-name
- /// template-id
- ///
- /// new-expression: [C++ 5.3.4]
- /// '::'[opt] 'new' new-placement[opt] new-type-id
- /// new-initializer[opt]
- /// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
- /// new-initializer[opt]
- ///
- /// delete-expression: [C++ 5.3.5]
- /// '::'[opt] 'delete' cast-expression
- /// '::'[opt] 'delete' '[' ']' cast-expression
- ///
- /// [GNU/Embarcadero] unary-type-trait:
- /// '__is_arithmetic'
- /// '__is_floating_point'
- /// '__is_integral'
- /// '__is_lvalue_expr'
- /// '__is_rvalue_expr'
- /// '__is_complete_type'
- /// '__is_void'
- /// '__is_array'
- /// '__is_function'
- /// '__is_reference'
- /// '__is_lvalue_reference'
- /// '__is_rvalue_reference'
- /// '__is_fundamental'
- /// '__is_object'
- /// '__is_scalar'
- /// '__is_compound'
- /// '__is_pointer'
- /// '__is_member_object_pointer'
- /// '__is_member_function_pointer'
- /// '__is_member_pointer'
- /// '__is_const'
- /// '__is_volatile'
- /// '__is_trivial'
- /// '__is_standard_layout'
- /// '__is_signed'
- /// '__is_unsigned'
- ///
- /// [GNU] unary-type-trait:
- /// '__has_nothrow_assign'
- /// '__has_nothrow_copy'
- /// '__has_nothrow_constructor'
- /// '__has_trivial_assign' [TODO]
- /// '__has_trivial_copy' [TODO]
- /// '__has_trivial_constructor'
- /// '__has_trivial_destructor'
- /// '__has_virtual_destructor'
- /// '__is_abstract' [TODO]
- /// '__is_class'
- /// '__is_empty' [TODO]
- /// '__is_enum'
- /// '__is_final'
- /// '__is_pod'
- /// '__is_polymorphic'
- /// '__is_sealed' [MS]
- /// '__is_trivial'
- /// '__is_union'
- /// '__has_unique_object_representations'
- ///
- /// [Clang] unary-type-trait:
- /// '__is_aggregate'
- /// '__trivially_copyable'
- ///
- /// binary-type-trait:
- /// [GNU] '__is_base_of'
- /// [MS] '__is_convertible_to'
- /// '__is_convertible'
- /// '__is_same'
- ///
- /// [Embarcadero] array-type-trait:
- /// '__array_rank'
- /// '__array_extent'
- ///
- /// [Embarcadero] expression-trait:
- /// '__is_lvalue_expr'
- /// '__is_rvalue_expr'
- /// \endverbatim
- ///
- ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
- bool isAddressOfOperand,
- bool &NotCastExpr,
- TypeCastState isTypeCast,
- bool isVectorLiteral) {
- ExprResult Res;
- tok::TokenKind SavedKind = Tok.getKind();
- NotCastExpr = false;
- // This handles all of cast-expression, unary-expression, postfix-expression,
- // and primary-expression. We handle them together like this for efficiency
- // and to simplify handling of an expression starting with a '(' token: which
- // may be one of a parenthesized expression, cast-expression, compound literal
- // expression, or statement expression.
- //
- // If the parsed tokens consist of a primary-expression, the cases below
- // break out of the switch; at the end we call ParsePostfixExpressionSuffix
- // to handle the postfix expression suffixes. Cases that cannot be followed
- // by postfix exprs should return without invoking
- // ParsePostfixExpressionSuffix.
- switch (SavedKind) {
- case tok::l_paren: {
- // If this expression is limited to being a unary-expression, the parent can
- // not start a cast expression.
- ParenParseOption ParenExprType =
- (isUnaryExpression && !getLangOpts().CPlusPlus) ? CompoundLiteral
- : CastExpr;
- ParsedType CastTy;
- SourceLocation RParenLoc;
- Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
- isTypeCast == IsTypeCast, CastTy, RParenLoc);
- if (isVectorLiteral)
- return Res;
- switch (ParenExprType) {
- case SimpleExpr: break; // Nothing else to do.
- case CompoundStmt: break; // Nothing else to do.
- case CompoundLiteral:
- // We parsed '(' type-name ')' '{' ... '}'. If any suffixes of
- // postfix-expression exist, parse them now.
- break;
- case CastExpr:
- // We have parsed the cast-expression and no postfix-expr pieces are
- // following.
- return Res;
- case FoldExpr:
- // We only parsed a fold-expression. There might be postfix-expr pieces
- // afterwards; parse them now.
- break;
- }
- break;
- }
- // primary-expression
- case tok::numeric_constant:
- // constant: integer-constant
- // constant: floating-constant
- Res = Actions.ActOnNumericConstant(Tok, /*UDLScope*/getCurScope());
- ConsumeToken();
- break;
- case tok::kw_true:
- case tok::kw_false:
- Res = ParseCXXBoolLiteral();
- break;
- case tok::kw___objc_yes:
- case tok::kw___objc_no:
- return ParseObjCBoolLiteral();
- case tok::kw_nullptr:
- Diag(Tok, diag::warn_cxx98_compat_nullptr);
- return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
- case tok::annot_primary_expr:
- assert(Res.get() == nullptr && "Stray primary-expression annotation?");
- Res = getExprAnnotation(Tok);
- ConsumeAnnotationToken();
- if (!Res.isInvalid() && Tok.is(tok::less))
- checkPotentialAngleBracket(Res);
- break;
- case tok::kw___super:
- case tok::kw_decltype:
- // Annotate the token and tail recurse.
- if (TryAnnotateTypeOrScopeToken())
- return ExprError();
- assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super));
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
- case tok::identifier: { // 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) {
- // Avoid the unnecessary parse-time lookup in the common case
- // where the syntax forbids a type.
- const Token &Next = NextToken();
- // If this identifier was reverted from a token ID, and the next token
- // is a parenthesis, this is likely to be a use of a type trait. Check
- // those tokens.
- if (Next.is(tok::l_paren) &&
- Tok.is(tok::identifier) &&
- Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) {
- IdentifierInfo *II = Tok.getIdentifierInfo();
- // Build up the mapping of revertible type traits, for future use.
- if (RevertibleTypeTraits.empty()) {
- #define RTT_JOIN(X,Y) X##Y
- #define REVERTIBLE_TYPE_TRAIT(Name) \
- RevertibleTypeTraits[PP.getIdentifierInfo(#Name)] \
- = RTT_JOIN(tok::kw_,Name)
- REVERTIBLE_TYPE_TRAIT(__is_abstract);
- REVERTIBLE_TYPE_TRAIT(__is_aggregate);
- REVERTIBLE_TYPE_TRAIT(__is_arithmetic);
- REVERTIBLE_TYPE_TRAIT(__is_array);
- REVERTIBLE_TYPE_TRAIT(__is_assignable);
- REVERTIBLE_TYPE_TRAIT(__is_base_of);
- REVERTIBLE_TYPE_TRAIT(__is_class);
- REVERTIBLE_TYPE_TRAIT(__is_complete_type);
- REVERTIBLE_TYPE_TRAIT(__is_compound);
- REVERTIBLE_TYPE_TRAIT(__is_const);
- REVERTIBLE_TYPE_TRAIT(__is_constructible);
- REVERTIBLE_TYPE_TRAIT(__is_convertible);
- REVERTIBLE_TYPE_TRAIT(__is_convertible_to);
- REVERTIBLE_TYPE_TRAIT(__is_destructible);
- REVERTIBLE_TYPE_TRAIT(__is_empty);
- REVERTIBLE_TYPE_TRAIT(__is_enum);
- REVERTIBLE_TYPE_TRAIT(__is_floating_point);
- REVERTIBLE_TYPE_TRAIT(__is_final);
- REVERTIBLE_TYPE_TRAIT(__is_function);
- REVERTIBLE_TYPE_TRAIT(__is_fundamental);
- REVERTIBLE_TYPE_TRAIT(__is_integral);
- REVERTIBLE_TYPE_TRAIT(__is_interface_class);
- REVERTIBLE_TYPE_TRAIT(__is_literal);
- REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
- REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
- REVERTIBLE_TYPE_TRAIT(__is_member_function_pointer);
- REVERTIBLE_TYPE_TRAIT(__is_member_object_pointer);
- REVERTIBLE_TYPE_TRAIT(__is_member_pointer);
- REVERTIBLE_TYPE_TRAIT(__is_nothrow_assignable);
- REVERTIBLE_TYPE_TRAIT(__is_nothrow_constructible);
- REVERTIBLE_TYPE_TRAIT(__is_nothrow_destructible);
- 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_rvalue_expr);
- REVERTIBLE_TYPE_TRAIT(__is_rvalue_reference);
- REVERTIBLE_TYPE_TRAIT(__is_same);
- REVERTIBLE_TYPE_TRAIT(__is_scalar);
- REVERTIBLE_TYPE_TRAIT(__is_sealed);
- REVERTIBLE_TYPE_TRAIT(__is_signed);
- REVERTIBLE_TYPE_TRAIT(__is_standard_layout);
- REVERTIBLE_TYPE_TRAIT(__is_trivial);
- REVERTIBLE_TYPE_TRAIT(__is_trivially_assignable);
- REVERTIBLE_TYPE_TRAIT(__is_trivially_constructible);
- REVERTIBLE_TYPE_TRAIT(__is_trivially_copyable);
- REVERTIBLE_TYPE_TRAIT(__is_union);
- REVERTIBLE_TYPE_TRAIT(__is_unsigned);
- REVERTIBLE_TYPE_TRAIT(__is_void);
- REVERTIBLE_TYPE_TRAIT(__is_volatile);
- #undef REVERTIBLE_TYPE_TRAIT
- #undef RTT_JOIN
- }
- // If we find that this is in fact the name of a type trait,
- // update the token kind in place and parse again to treat it as
- // the appropriate kind of type trait.
- llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known
- = RevertibleTypeTraits.find(II);
- if (Known != RevertibleTypeTraits.end()) {
- Tok.setKind(Known->second);
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
- }
- }
- if ((!ColonIsSacred && Next.is(tok::colon)) ||
- Next.isOneOf(tok::coloncolon, tok::less, tok::l_paren,
- tok::l_brace)) {
- // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
- if (TryAnnotateTypeOrScopeToken())
- return ExprError();
- if (!Tok.is(tok::identifier))
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
- }
- }
- // Consume the identifier so that we can see if it is followed by a '(' or
- // '.'.
- IdentifierInfo &II = *Tok.getIdentifierInfo();
- SourceLocation ILoc = ConsumeToken();
- // Support 'Class.property' and 'super.property' notation.
- if (getLangOpts().ObjC1 && Tok.is(tok::period) &&
- (Actions.getTypeName(II, ILoc, getCurScope()) ||
- // Allow the base to be 'super' if in an objc-method.
- (&II == Ident_super && getCurScope()->isInObjcMethodScope()))) {
- ConsumeToken();
- if (Tok.is(tok::code_completion) && &II != Ident_super) {
- Actions.CodeCompleteObjCClassPropertyRefExpr(
- getCurScope(), II, ILoc, ExprStatementTokLoc == ILoc);
- cutOffParsing();
- return ExprError();
- }
- // Allow either an identifier or the keyword 'class' (in C++).
- if (Tok.isNot(tok::identifier) &&
- !(getLangOpts().CPlusPlus && Tok.is(tok::kw_class))) {
- Diag(Tok, diag::err_expected_property_name);
- return ExprError();
- }
- IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();
- SourceLocation PropertyLoc = ConsumeToken();
- Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName,
- ILoc, PropertyLoc);
- break;
- }
- // In an Objective-C method, if we have "super" followed by an identifier,
- // the token sequence is ill-formed. However, if there's a ':' or ']' after
- // that identifier, this is probably a message send with a missing open
- // bracket. Treat it as such.
- if (getLangOpts().ObjC1 && &II == Ident_super && !InMessageExpression &&
- getCurScope()->isInObjcMethodScope() &&
- ((Tok.is(tok::identifier) &&
- (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) ||
- Tok.is(tok::code_completion))) {
- Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, nullptr,
- nullptr);
- break;
- }
- // If we have an Objective-C class name followed by an identifier
- // and either ':' or ']', this is an Objective-C class message
- // send that's missing the opening '['. Recovery
- // appropriately. Also take this path if we're performing code
- // completion after an Objective-C class name.
- if (getLangOpts().ObjC1 &&
- ((Tok.is(tok::identifier) && !InMessageExpression) ||
- Tok.is(tok::code_completion))) {
- const Token& Next = NextToken();
- if (Tok.is(tok::code_completion) ||
- Next.is(tok::colon) || Next.is(tok::r_square))
- if (ParsedType Typ = Actions.getTypeName(II, ILoc, getCurScope()))
- if (Typ.get()->isObjCObjectOrInterfaceType()) {
- // Fake up a Declarator to use with ActOnTypeName.
- DeclSpec DS(AttrFactory);
- DS.SetRangeStart(ILoc);
- DS.SetRangeEnd(ILoc);
- const char *PrevSpec = nullptr;
- unsigned DiagID;
- DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ,
- Actions.getASTContext().getPrintingPolicy());
- Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
- TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
- DeclaratorInfo);
- if (Ty.isInvalid())
- break;
- Res = ParseObjCMessageExpressionBody(SourceLocation(),
- SourceLocation(),
- Ty.get(), nullptr);
- break;
- }
- }
- // Make sure to pass down the right value for isAddressOfOperand.
- if (isAddressOfOperand && isPostfixExpressionSuffixStart())
- isAddressOfOperand = false;
- // Function designators are allowed to be undeclared (C99 6.5.1p2), so we
- // need to know whether or not this identifier is a function designator or
- // not.
- UnqualifiedId Name;
- CXXScopeSpec ScopeSpec;
- SourceLocation TemplateKWLoc;
- Token Replacement;
- auto Validator = llvm::make_unique<CastExpressionIdValidator>(
- Tok, isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
- Validator->IsAddressOfOperand = isAddressOfOperand;
- if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) {
- Validator->WantExpressionKeywords = false;
- Validator->WantRemainingKeywords = false;
- } else {
- Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren);
- }
- Name.setIdentifier(&II, ILoc);
- Res = Actions.ActOnIdExpression(
- getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren),
- isAddressOfOperand, std::move(Validator),
- /*IsInlineAsmIdentifier=*/false,
- Tok.is(tok::r_paren) ? nullptr : &Replacement);
- if (!Res.isInvalid() && Res.isUnset()) {
- UnconsumeToken(Replacement);
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
- }
- if (!Res.isInvalid() && Tok.is(tok::less))
- checkPotentialAngleBracket(Res);
- break;
- }
- case tok::char_constant: // constant: character-constant
- case tok::wide_char_constant:
- case tok::utf8_char_constant:
- case tok::utf16_char_constant:
- case tok::utf32_char_constant:
- Res = Actions.ActOnCharacterConstant(Tok, /*UDLScope*/getCurScope());
- ConsumeToken();
- break;
- case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
- case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
- case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS]
- case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS]
- case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS]
- case tok::kw_L__FUNCSIG__: // primary-expression: L__FUNCSIG__ [MS]
- case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
- Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
- ConsumeToken();
- break;
- case tok::string_literal: // primary-expression: string-literal
- case tok::wide_string_literal:
- case tok::utf8_string_literal:
- case tok::utf16_string_literal:
- case tok::utf32_string_literal:
- Res = ParseStringLiteralExpression(true);
- break;
- case tok::kw__Generic: // primary-expression: generic-selection [C11 6.5.1]
- Res = ParseGenericSelectionExpression();
- break;
- case tok::kw___builtin_available:
- return ParseAvailabilityCheckExpr(Tok.getLocation());
- case tok::kw___builtin_va_arg:
- case tok::kw___builtin_offsetof:
- case tok::kw___builtin_choose_expr:
- case tok::kw___builtin_astype: // primary-expression: [OCL] as_type()
- case tok::kw___builtin_convertvector:
- return ParseBuiltinPrimaryExpression();
- case tok::kw___null:
- return Actions.ActOnGNUNullExpr(ConsumeToken());
- case tok::plusplus: // unary-expression: '++' unary-expression [C99]
- case tok::minusminus: { // unary-expression: '--' unary-expression [C99]
- // C++ [expr.unary] has:
- // unary-expression:
- // ++ cast-expression
- // -- cast-expression
- Token SavedTok = Tok;
- ConsumeToken();
- // One special case is implicitly handled here: if the preceding tokens are
- // an ambiguous cast expression, such as "(T())++", then we recurse to
- // determine whether the '++' is prefix or postfix.
- Res = ParseCastExpression(!getLangOpts().CPlusPlus,
- /*isAddressOfOperand*/false, NotCastExpr,
- NotTypeCast);
- if (NotCastExpr) {
- // If we return with NotCastExpr = true, we must not consume any tokens,
- // so put the token back where we found it.
- assert(Res.isInvalid());
- UnconsumeToken(SavedTok);
- return ExprError();
- }
- if (!Res.isInvalid())
- Res = Actions.ActOnUnaryOp(getCurScope(), SavedTok.getLocation(),
- SavedKind, Res.get());
- return Res;
- }
- case tok::amp: { // unary-expression: '&' cast-expression
- // Special treatment because of member pointers
- SourceLocation SavedLoc = ConsumeToken();
- Res = ParseCastExpression(false, true);
- if (!Res.isInvalid())
- Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
- return Res;
- }
- case tok::star: // unary-expression: '*' cast-expression
- case tok::plus: // unary-expression: '+' cast-expression
- case tok::minus: // unary-expression: '-' cast-expression
- case tok::tilde: // unary-expression: '~' cast-expression
- case tok::exclaim: // unary-expression: '!' cast-expression
- case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
- case tok::kw___imag: { // unary-expression: '__imag' cast-expression [GNU]
- SourceLocation SavedLoc = ConsumeToken();
- Res = ParseCastExpression(false);
- if (!Res.isInvalid())
- Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
- return Res;
- }
- case tok::kw_co_await: { // unary-expression: 'co_await' cast-expression
- SourceLocation CoawaitLoc = ConsumeToken();
- Res = ParseCastExpression(false);
- if (!Res.isInvalid())
- Res = Actions.ActOnCoawaitExpr(getCurScope(), CoawaitLoc, Res.get());
- return Res;
- }
- case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU]
- // __extension__ silences extension warnings in the subexpression.
- ExtensionRAIIObject O(Diags); // Use RAII to do this.
- SourceLocation SavedLoc = ConsumeToken();
- Res = ParseCastExpression(false);
- if (!Res.isInvalid())
- Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
- return Res;
- }
- case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')'
- if (!getLangOpts().C11)
- Diag(Tok, diag::ext_c11_alignment) << Tok.getName();
- // fallthrough
- case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')'
- case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
- // unary-expression: '__alignof' '(' type-name ')'
- case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
- // unary-expression: 'sizeof' '(' type-name ')'
- case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression
- // unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')'
- case tok::kw___builtin_omp_required_simd_align:
- return ParseUnaryExprOrTypeTraitExpression();
- case tok::ampamp: { // unary-expression: '&&' identifier
- SourceLocation AmpAmpLoc = ConsumeToken();
- if (Tok.isNot(tok::identifier))
- return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
- if (getCurScope()->getFnParent() == nullptr)
- return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn));
- Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
- LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
- Tok.getLocation());
- Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(), LD);
- ConsumeToken();
- return Res;
- }
- case tok::kw_const_cast:
- case tok::kw_dynamic_cast:
- case tok::kw_reinterpret_cast:
- case tok::kw_static_cast:
- Res = ParseCXXCasts();
- break;
- case tok::kw_typeid:
- Res = ParseCXXTypeid();
- break;
- case tok::kw___uuidof:
- Res = ParseCXXUuidof();
- break;
- case tok::kw_this:
- Res = ParseCXXThis();
- break;
- case tok::annot_typename:
- if (isStartOfObjCClassMessageMissingOpenBracket()) {
- ParsedType Type = getTypeAnnotation(Tok);
- // Fake up a Declarator to use with ActOnTypeName.
- DeclSpec DS(AttrFactory);
- DS.SetRangeStart(Tok.getLocation());
- DS.SetRangeEnd(Tok.getLastLoc());
- const char *PrevSpec = nullptr;
- unsigned DiagID;
- DS.SetTypeSpecType(TST_typename, Tok.getAnnotationEndLoc(),
- PrevSpec, DiagID, Type,
- Actions.getASTContext().getPrintingPolicy());
- Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
- TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
- if (Ty.isInvalid())
- break;
- ConsumeAnnotationToken();
- Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
- Ty.get(), nullptr);
- break;
- }
- // Fall through
- case tok::annot_decltype:
- case tok::kw_char:
- case tok::kw_wchar_t:
- case tok::kw_char8_t:
- case tok::kw_char16_t:
- case tok::kw_char32_t:
- case tok::kw_bool:
- case tok::kw_short:
- case tok::kw_int:
- case tok::kw_long:
- case tok::kw___int64:
- case tok::kw___int128:
- case tok::kw_signed:
- case tok::kw_unsigned:
- case tok::kw_half:
- case tok::kw_float:
- case tok::kw_double:
- case tok::kw__Float16:
- case tok::kw___float128:
- case tok::kw_void:
- case tok::kw_typename:
- case tok::kw_typeof:
- case tok::kw___vector:
- #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
- #include "clang/Basic/OpenCLImageTypes.def"
- {
- if (!getLangOpts().CPlusPlus) {
- Diag(Tok, diag::err_expected_expression);
- return ExprError();
- }
- if (SavedKind == tok::kw_typename) {
- // postfix-expression: typename-specifier '(' expression-list[opt] ')'
- // typename-specifier braced-init-list
- if (TryAnnotateTypeOrScopeToken())
- return ExprError();
- if (!Actions.isSimpleTypeSpecifier(Tok.getKind()))
- // We are trying to parse a simple-type-specifier but might not get such
- // a token after error recovery.
- return ExprError();
- }
- // postfix-expression: simple-type-specifier '(' expression-list[opt] ')'
- // simple-type-specifier braced-init-list
- //
- DeclSpec DS(AttrFactory);
- ParseCXXSimpleTypeSpecifier(DS);
- if (Tok.isNot(tok::l_paren) &&
- (!getLangOpts().CPlusPlus11 || Tok.isNot(tok::l_brace)))
- return ExprError(Diag(Tok, diag::err_expected_lparen_after_type)
- << DS.getSourceRange());
- if (Tok.is(tok::l_brace))
- Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
- Res = ParseCXXTypeConstructExpression(DS);
- break;
- }
- case tok::annot_cxxscope: { // [C++] id-expression: qualified-id
- // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
- // (We can end up in this situation after tentative parsing.)
- if (TryAnnotateTypeOrScopeToken())
- return ExprError();
- if (!Tok.is(tok::annot_cxxscope))
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
- Token Next = NextToken();
- if (Next.is(tok::annot_template_id)) {
- TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next);
- if (TemplateId->Kind == TNK_Type_template) {
- // We have a qualified template-id that we know refers to a
- // type, translate it into a type and continue parsing as a
- // cast expression.
- CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, nullptr,
- /*EnteringContext=*/false);
- AnnotateTemplateIdTokenAsType();
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
- }
- }
- // Parse as an id-expression.
- Res = ParseCXXIdExpression(isAddressOfOperand);
- break;
- }
- case tok::annot_template_id: { // [C++] template-id
- TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
- if (TemplateId->Kind == TNK_Type_template) {
- // We have a template-id that we know refers to a type,
- // translate it into a type and continue parsing as a cast
- // expression.
- AnnotateTemplateIdTokenAsType();
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
- }
- // Fall through to treat the template-id as an id-expression.
- LLVM_FALLTHROUGH;
- }
- case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id
- Res = ParseCXXIdExpression(isAddressOfOperand);
- break;
- case tok::coloncolon: {
- // ::foo::bar -> global qualified name etc. If TryAnnotateTypeOrScopeToken
- // annotates the token, tail recurse.
- if (TryAnnotateTypeOrScopeToken())
- return ExprError();
- if (!Tok.is(tok::coloncolon))
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
- // ::new -> [C++] new-expression
- // ::delete -> [C++] delete-expression
- SourceLocation CCLoc = ConsumeToken();
- if (Tok.is(tok::kw_new))
- return ParseCXXNewExpression(true, CCLoc);
- if (Tok.is(tok::kw_delete))
- return ParseCXXDeleteExpression(true, CCLoc);
- // This is not a type name or scope specifier, it is an invalid expression.
- Diag(CCLoc, diag::err_expected_expression);
- return ExprError();
- }
- case tok::kw_new: // [C++] new-expression
- return ParseCXXNewExpression(false, Tok.getLocation());
- case tok::kw_delete: // [C++] delete-expression
- return ParseCXXDeleteExpression(false, Tok.getLocation());
- case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')'
- Diag(Tok, diag::warn_cxx98_compat_noexcept_expr);
- SourceLocation KeyLoc = ConsumeToken();
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen_after, "noexcept"))
- return ExprError();
- // C++11 [expr.unary.noexcept]p1:
- // The noexcept operator determines whether the evaluation of its operand,
- // which is an unevaluated operand, can throw an exception.
- EnterExpressionEvaluationContext Unevaluated(
- Actions, Sema::ExpressionEvaluationContext::Unevaluated);
- ExprResult Result = ParseExpression();
- T.consumeClose();
- if (!Result.isInvalid())
- Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(),
- Result.get(), T.getCloseLocation());
- return Result;
- }
- #define TYPE_TRAIT(N,Spelling,K) \
- case tok::kw_##Spelling:
- #include "clang/Basic/TokenKinds.def"
- return ParseTypeTrait();
- case tok::kw___array_rank:
- case tok::kw___array_extent:
- return ParseArrayTypeTrait();
- case tok::kw___is_lvalue_expr:
- case tok::kw___is_rvalue_expr:
- return ParseExpressionTrait();
- case tok::at: {
- SourceLocation AtLoc = ConsumeToken();
- return ParseObjCAtExpression(AtLoc);
- }
- case tok::caret:
- Res = ParseBlockLiteralExpression();
- break;
- case tok::code_completion: {
- Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
- cutOffParsing();
- return ExprError();
- }
- case tok::l_square:
- if (getLangOpts().CPlusPlus11) {
- if (getLangOpts().ObjC1) {
- // C++11 lambda expressions and Objective-C message sends both start with a
- // square bracket. There are three possibilities here:
- // we have a valid lambda expression, we have an invalid lambda
- // expression, or we have something that doesn't appear to be a lambda.
- // If we're in the last case, we fall back to ParseObjCMessageExpression.
- Res = TryParseLambdaExpression();
- if (!Res.isInvalid() && !Res.get())
- Res = ParseObjCMessageExpression();
- break;
- }
- Res = ParseLambdaExpression();
- break;
- }
- if (getLangOpts().ObjC1) {
- Res = ParseObjCMessageExpression();
- break;
- }
- // FALL THROUGH.
- default:
- NotCastExpr = true;
- return ExprError();
- }
- // Check to see whether Res is a function designator only. If it is and we
- // are compiling for OpenCL, we need to return an error as this implies
- // that the address of the function is being taken, which is illegal in CL.
- // These can be followed by postfix-expr pieces.
- Res = ParsePostfixExpressionSuffix(Res);
- if (getLangOpts().OpenCL)
- if (Expr *PostfixExpr = Res.get()) {
- QualType Ty = PostfixExpr->getType();
- if (!Ty.isNull() && Ty->isFunctionType()) {
- Diag(PostfixExpr->getExprLoc(),
- diag::err_opencl_taking_function_address_parser);
- return ExprError();
- }
- }
- return Res;
- }
- /// Once the leading part of a postfix-expression is parsed, this
- /// method parses any suffixes that apply.
- ///
- /// \verbatim
- /// postfix-expression: [C99 6.5.2]
- /// primary-expression
- /// postfix-expression '[' expression ']'
- /// postfix-expression '[' braced-init-list ']'
- /// postfix-expression '(' argument-expression-list[opt] ')'
- /// postfix-expression '.' identifier
- /// postfix-expression '->' identifier
- /// postfix-expression '++'
- /// postfix-expression '--'
- /// '(' type-name ')' '{' initializer-list '}'
- /// '(' type-name ')' '{' initializer-list ',' '}'
- ///
- /// argument-expression-list: [C99 6.5.2]
- /// argument-expression ...[opt]
- /// argument-expression-list ',' assignment-expression ...[opt]
- /// \endverbatim
- ExprResult
- Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
- // Now that the primary-expression piece of the postfix-expression has been
- // parsed, see if there are any postfix-expression pieces here.
- SourceLocation Loc;
- while (1) {
- switch (Tok.getKind()) {
- case tok::code_completion:
- if (InMessageExpression)
- return LHS;
- Actions.CodeCompletePostfixExpression(getCurScope(), LHS);
- cutOffParsing();
- return ExprError();
- case tok::identifier:
- // If we see identifier: after an expression, and we're not already in a
- // message send, then this is probably a message send with a missing
- // opening bracket '['.
- if (getLangOpts().ObjC1 && !InMessageExpression &&
- (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {
- LHS = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
- nullptr, LHS.get());
- break;
- }
- // Fall through; this isn't a message send.
- LLVM_FALLTHROUGH;
- default: // Not a postfix-expression suffix.
- return LHS;
- case tok::l_square: { // postfix-expression: p-e '[' expression ']'
- // If we have a array postfix expression that starts on a new line and
- // Objective-C is enabled, it is highly likely that the user forgot a
- // semicolon after the base expression and that the array postfix-expr is
- // actually another message send. In this case, do some look-ahead to see
- // if the contents of the square brackets are obviously not a valid
- // expression and recover by pretending there is no suffix.
- if (getLangOpts().ObjC1 && Tok.isAtStartOfLine() &&
- isSimpleObjCMessageExpression())
- return LHS;
- // Reject array indices starting with a lambda-expression. '[[' is
- // reserved for attributes.
- if (CheckProhibitedCXX11Attribute()) {
- (void)Actions.CorrectDelayedTyposInExpr(LHS);
- return ExprError();
- }
- BalancedDelimiterTracker T(*this, tok::l_square);
- T.consumeOpen();
- Loc = T.getOpenLocation();
- ExprResult Idx, Length;
- SourceLocation ColonLoc;
- if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
- Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
- Idx = ParseBraceInitializer();
- } else if (getLangOpts().OpenMP) {
- ColonProtectionRAIIObject RAII(*this);
- // Parse [: or [ expr or [ expr :
- if (!Tok.is(tok::colon)) {
- // [ expr
- Idx = ParseExpression();
- }
- if (Tok.is(tok::colon)) {
- // Consume ':'
- ColonLoc = ConsumeToken();
- if (Tok.isNot(tok::r_square))
- Length = ParseExpression();
- }
- } else
- Idx = ParseExpression();
- SourceLocation RLoc = Tok.getLocation();
- ExprResult OrigLHS = LHS;
- if (!LHS.isInvalid() && !Idx.isInvalid() && !Length.isInvalid() &&
- Tok.is(tok::r_square)) {
- if (ColonLoc.isValid()) {
- LHS = Actions.ActOnOMPArraySectionExpr(LHS.get(), Loc, Idx.get(),
- ColonLoc, Length.get(), RLoc);
- } else {
- LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc,
- Idx.get(), RLoc);
- }
- } else {
- LHS = ExprError();
- }
- if (LHS.isInvalid()) {
- (void)Actions.CorrectDelayedTyposInExpr(OrigLHS);
- (void)Actions.CorrectDelayedTyposInExpr(Idx);
- (void)Actions.CorrectDelayedTyposInExpr(Length);
- LHS = ExprError();
- Idx = ExprError();
- }
- // Match the ']'.
- T.consumeClose();
- break;
- }
- case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'
- case tok::lesslessless: { // p-e: p-e '<<<' argument-expression-list '>>>'
- // '(' argument-expression-list[opt] ')'
- tok::TokenKind OpKind = Tok.getKind();
- InMessageExpressionRAIIObject InMessage(*this, false);
- Expr *ExecConfig = nullptr;
- BalancedDelimiterTracker PT(*this, tok::l_paren);
- if (OpKind == tok::lesslessless) {
- ExprVector ExecConfigExprs;
- CommaLocsTy ExecConfigCommaLocs;
- SourceLocation OpenLoc = ConsumeToken();
- if (ParseSimpleExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) {
- (void)Actions.CorrectDelayedTyposInExpr(LHS);
- LHS = ExprError();
- }
- SourceLocation CloseLoc;
- if (TryConsumeToken(tok::greatergreatergreater, CloseLoc)) {
- } else if (LHS.isInvalid()) {
- SkipUntil(tok::greatergreatergreater, StopAtSemi);
- } else {
- // There was an error closing the brackets
- Diag(Tok, diag::err_expected) << tok::greatergreatergreater;
- Diag(OpenLoc, diag::note_matching) << tok::lesslessless;
- SkipUntil(tok::greatergreatergreater, StopAtSemi);
- LHS = ExprError();
- }
- if (!LHS.isInvalid()) {
- if (ExpectAndConsume(tok::l_paren))
- LHS = ExprError();
- else
- Loc = PrevTokLocation;
- }
- if (!LHS.isInvalid()) {
- ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(),
- OpenLoc,
- ExecConfigExprs,
- CloseLoc);
- if (ECResult.isInvalid())
- LHS = ExprError();
- else
- ExecConfig = ECResult.get();
- }
- } else {
- PT.consumeOpen();
- Loc = PT.getOpenLocation();
- }
- ExprVector ArgExprs;
- CommaLocsTy CommaLocs;
- if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteCall(getCurScope(), LHS.get(), None);
- cutOffParsing();
- return ExprError();
- }
- if (OpKind == tok::l_paren || !LHS.isInvalid()) {
- if (Tok.isNot(tok::r_paren)) {
- if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
- Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
- })) {
- (void)Actions.CorrectDelayedTyposInExpr(LHS);
- LHS = ExprError();
- } else if (LHS.isInvalid()) {
- for (auto &E : ArgExprs)
- Actions.CorrectDelayedTyposInExpr(E);
- }
- }
- }
- // Match the ')'.
- if (LHS.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- } else if (Tok.isNot(tok::r_paren)) {
- bool HadDelayedTypo = false;
- if (Actions.CorrectDelayedTyposInExpr(LHS).get() != LHS.get())
- HadDelayedTypo = true;
- for (auto &E : ArgExprs)
- if (Actions.CorrectDelayedTyposInExpr(E).get() != E)
- HadDelayedTypo = true;
- // If there were delayed typos in the LHS or ArgExprs, call SkipUntil
- // instead of PT.consumeClose() to avoid emitting extra diagnostics for
- // the unmatched l_paren.
- if (HadDelayedTypo)
- SkipUntil(tok::r_paren, StopAtSemi);
- else
- PT.consumeClose();
- LHS = ExprError();
- } else {
- assert((ArgExprs.size() == 0 ||
- ArgExprs.size()-1 == CommaLocs.size())&&
- "Unexpected number of commas!");
- LHS = Actions.ActOnCallExpr(getCurScope(), LHS.get(), Loc,
- ArgExprs, Tok.getLocation(),
- ExecConfig);
- PT.consumeClose();
- }
- break;
- }
- case tok::arrow:
- case tok::period: {
- // postfix-expression: p-e '->' template[opt] id-expression
- // postfix-expression: p-e '.' template[opt] id-expression
- tok::TokenKind OpKind = Tok.getKind();
- SourceLocation OpLoc = ConsumeToken(); // Eat the "." or "->" token.
- CXXScopeSpec SS;
- ParsedType ObjectType;
- bool MayBePseudoDestructor = false;
- Expr* OrigLHS = !LHS.isInvalid() ? LHS.get() : nullptr;
- if (getLangOpts().CPlusPlus && !LHS.isInvalid()) {
- Expr *Base = OrigLHS;
- const Type* BaseType = Base->getType().getTypePtrOrNull();
- if (BaseType && Tok.is(tok::l_paren) &&
- (BaseType->isFunctionType() ||
- BaseType->isSpecificPlaceholderType(BuiltinType::BoundMember))) {
- Diag(OpLoc, diag::err_function_is_not_record)
- << OpKind << Base->getSourceRange()
- << FixItHint::CreateRemoval(OpLoc);
- return ParsePostfixExpressionSuffix(Base);
- }
- LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), Base,
- OpLoc, OpKind, ObjectType,
- MayBePseudoDestructor);
- if (LHS.isInvalid())
- break;
- ParseOptionalCXXScopeSpecifier(SS, ObjectType,
- /*EnteringContext=*/false,
- &MayBePseudoDestructor);
- if (SS.isNotEmpty())
- ObjectType = nullptr;
- }
- if (Tok.is(tok::code_completion)) {
- tok::TokenKind CorrectedOpKind =
- OpKind == tok::arrow ? tok::period : tok::arrow;
- ExprResult CorrectedLHS(/*IsInvalid=*/true);
- if (getLangOpts().CPlusPlus && OrigLHS) {
- const bool DiagsAreSuppressed = Diags.getSuppressAllDiagnostics();
- Diags.setSuppressAllDiagnostics(true);
- CorrectedLHS = Actions.ActOnStartCXXMemberReference(
- getCurScope(), OrigLHS, OpLoc, CorrectedOpKind, ObjectType,
- MayBePseudoDestructor);
- Diags.setSuppressAllDiagnostics(DiagsAreSuppressed);
- }
- Expr *Base = LHS.get();
- Expr *CorrectedBase = CorrectedLHS.get();
- // Code completion for a member access expression.
- Actions.CodeCompleteMemberReferenceExpr(
- getCurScope(), Base, CorrectedBase, OpLoc, OpKind == tok::arrow,
- Base && ExprStatementTokLoc == Base->getBeginLoc());
- cutOffParsing();
- return ExprError();
- }
- if (MayBePseudoDestructor && !LHS.isInvalid()) {
- LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS,
- ObjectType);
- break;
- }
- // Either the action has told us that this cannot be a
- // pseudo-destructor expression (based on the type of base
- // expression), or we didn't see a '~' in the right place. We
- // can still parse a destructor name here, but in that case it
- // names a real destructor.
- // Allow explicit constructor calls in Microsoft mode.
- // FIXME: Add support for explicit call of template constructor.
- SourceLocation TemplateKWLoc;
- UnqualifiedId Name;
- if (getLangOpts().ObjC2 && OpKind == tok::period &&
- Tok.is(tok::kw_class)) {
- // Objective-C++:
- // After a '.' in a member access expression, treat the keyword
- // 'class' as if it were an identifier.
- //
- // This hack allows property access to the 'class' method because it is
- // such a common method name. For other C++ keywords that are
- // Objective-C method names, one must use the message send syntax.
- IdentifierInfo *Id = Tok.getIdentifierInfo();
- SourceLocation Loc = ConsumeToken();
- Name.setIdentifier(Id, Loc);
- } else if (ParseUnqualifiedId(SS,
- /*EnteringContext=*/false,
- /*AllowDestructorName=*/true,
- /*AllowConstructorName=*/
- getLangOpts().MicrosoftExt,
- /*AllowDeductionGuide=*/false,
- ObjectType, &TemplateKWLoc, Name)) {
- (void)Actions.CorrectDelayedTyposInExpr(LHS);
- LHS = ExprError();
- }
- if (!LHS.isInvalid())
- LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,
- OpKind, SS, TemplateKWLoc, Name,
- CurParsedObjCImpl ? CurParsedObjCImpl->Dcl
- : nullptr);
- if (!LHS.isInvalid() && Tok.is(tok::less))
- checkPotentialAngleBracket(LHS);
- break;
- }
- case tok::plusplus: // postfix-expression: postfix-expression '++'
- case tok::minusminus: // postfix-expression: postfix-expression '--'
- if (!LHS.isInvalid()) {
- LHS = Actions.ActOnPostfixUnaryOp(getCurScope(), Tok.getLocation(),
- Tok.getKind(), LHS.get());
- }
- ConsumeToken();
- break;
- }
- }
- }
- /// ParseExprAfterUnaryExprOrTypeTrait - We parsed a typeof/sizeof/alignof/
- /// vec_step and we are at the start of an expression or a parenthesized
- /// type-id. OpTok is the operand token (typeof/sizeof/alignof). Returns the
- /// expression (isCastExpr == false) or the type (isCastExpr == true).
- ///
- /// \verbatim
- /// unary-expression: [C99 6.5.3]
- /// 'sizeof' unary-expression
- /// 'sizeof' '(' type-name ')'
- /// [GNU] '__alignof' unary-expression
- /// [GNU] '__alignof' '(' type-name ')'
- /// [C11] '_Alignof' '(' type-name ')'
- /// [C++0x] 'alignof' '(' type-id ')'
- ///
- /// [GNU] typeof-specifier:
- /// typeof ( expressions )
- /// typeof ( type-name )
- /// [GNU/C++] typeof unary-expression
- ///
- /// [OpenCL 1.1 6.11.12] vec_step built-in function:
- /// vec_step ( expressions )
- /// vec_step ( type-name )
- /// \endverbatim
- ExprResult
- Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
- bool &isCastExpr,
- 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,
- tok::kw___builtin_omp_required_simd_align) &&
- "Not a typeof/sizeof/alignof/vec_step expression!");
- ExprResult Operand;
- // If the operand doesn't start with an '(', it must be an expression.
- if (Tok.isNot(tok::l_paren)) {
- // If construct allows a form without parenthesis, user may forget to put
- // pathenthesis around type name.
- if (OpTok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof,
- tok::kw__Alignof)) {
- if (isTypeIdUnambiguously()) {
- DeclSpec DS(AttrFactory);
- ParseSpecifierQualifierList(DS);
- Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
- ParseDeclarator(DeclaratorInfo);
- SourceLocation LParenLoc = PP.getLocForEndOfToken(OpTok.getLocation());
- SourceLocation RParenLoc = PP.getLocForEndOfToken(PrevTokLocation);
- Diag(LParenLoc, diag::err_expected_parentheses_around_typename)
- << OpTok.getName()
- << FixItHint::CreateInsertion(LParenLoc, "(")
- << FixItHint::CreateInsertion(RParenLoc, ")");
- isCastExpr = true;
- return ExprEmpty();
- }
- }
- isCastExpr = false;
- if (OpTok.is(tok::kw_typeof) && !getLangOpts().CPlusPlus) {
- Diag(Tok, diag::err_expected_after) << OpTok.getIdentifierInfo()
- << tok::l_paren;
- return ExprError();
- }
- Operand = ParseCastExpression(true/*isUnaryExpression*/);
- } else {
- // If it starts with a '(', we know that it is either a parenthesized
- // type-name, or it is a unary-expression that starts with a compound
- // literal, or starts with a primary-expression that is a parenthesized
- // expression.
- ParenParseOption ExprType = CastExpr;
- SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
- Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
- false, CastTy, RParenLoc);
- CastRange = SourceRange(LParenLoc, RParenLoc);
- // If ParseParenExpression parsed a '(typename)' sequence only, then this is
- // a type.
- if (ExprType == CastExpr) {
- isCastExpr = true;
- return ExprEmpty();
- }
- if (getLangOpts().CPlusPlus || OpTok.isNot(tok::kw_typeof)) {
- // 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
- // pieces. Parse these now if present.
- if (!Operand.isInvalid())
- Operand = ParsePostfixExpressionSuffix(Operand.get());
- }
- }
- // If we get here, the operand to the typeof/sizeof/alignof was an expression.
- isCastExpr = false;
- return Operand;
- }
- /// Parse a sizeof or alignof expression.
- ///
- /// \verbatim
- /// unary-expression: [C99 6.5.3]
- /// 'sizeof' unary-expression
- /// 'sizeof' '(' type-name ')'
- /// [C++11] 'sizeof' '...' '(' identifier ')'
- /// [GNU] '__alignof' unary-expression
- /// [GNU] '__alignof' '(' type-name ')'
- /// [C11] '_Alignof' '(' type-name ')'
- /// [C++11] 'alignof' '(' type-id ')'
- /// \endverbatim
- ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
- assert(Tok.isOneOf(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 sizeof/alignof/vec_step expression!");
- Token OpTok = Tok;
- ConsumeToken();
- // [C++11] 'sizeof' '...' '(' identifier ')'
- if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof)) {
- SourceLocation EllipsisLoc = ConsumeToken();
- SourceLocation LParenLoc, RParenLoc;
- IdentifierInfo *Name = nullptr;
- SourceLocation NameLoc;
- if (Tok.is(tok::l_paren)) {
- BalancedDelimiterTracker T(*this, tok::l_paren);
- T.consumeOpen();
- LParenLoc = T.getOpenLocation();
- if (Tok.is(tok::identifier)) {
- Name = Tok.getIdentifierInfo();
- NameLoc = ConsumeToken();
- T.consumeClose();
- RParenLoc = T.getCloseLocation();
- if (RParenLoc.isInvalid())
- RParenLoc = PP.getLocForEndOfToken(NameLoc);
- } else {
- Diag(Tok, diag::err_expected_parameter_pack);
- SkipUntil(tok::r_paren, StopAtSemi);
- }
- } else if (Tok.is(tok::identifier)) {
- Name = Tok.getIdentifierInfo();
- NameLoc = ConsumeToken();
- LParenLoc = PP.getLocForEndOfToken(EllipsisLoc);
- RParenLoc = PP.getLocForEndOfToken(NameLoc);
- Diag(LParenLoc, diag::err_paren_sizeof_parameter_pack)
- << Name
- << FixItHint::CreateInsertion(LParenLoc, "(")
- << FixItHint::CreateInsertion(RParenLoc, ")");
- } else {
- Diag(Tok, diag::err_sizeof_parameter_pack);
- }
- if (!Name)
- return ExprError();
- EnterExpressionEvaluationContext Unevaluated(
- Actions, Sema::ExpressionEvaluationContext::Unevaluated,
- Sema::ReuseLambdaContextDecl);
- return Actions.ActOnSizeofParameterPackExpr(getCurScope(),
- OpTok.getLocation(),
- *Name, NameLoc,
- RParenLoc);
- }
- if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))
- Diag(OpTok, diag::warn_cxx98_compat_alignof);
- EnterExpressionEvaluationContext Unevaluated(
- Actions, Sema::ExpressionEvaluationContext::Unevaluated,
- Sema::ReuseLambdaContextDecl);
- bool isCastExpr;
- ParsedType CastTy;
- SourceRange CastRange;
- ExprResult Operand = ParseExprAfterUnaryExprOrTypeTrait(OpTok,
- isCastExpr,
- CastTy,
- CastRange);
- UnaryExprOrTypeTrait ExprKind = UETT_SizeOf;
- if (OpTok.isOneOf(tok::kw_alignof, tok::kw___alignof, tok::kw__Alignof))
- ExprKind = UETT_AlignOf;
- else if (OpTok.is(tok::kw_vec_step))
- ExprKind = UETT_VecStep;
- else if (OpTok.is(tok::kw___builtin_omp_required_simd_align))
- ExprKind = UETT_OpenMPRequiredSimdAlign;
- if (isCastExpr)
- return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),
- ExprKind,
- /*isType=*/true,
- CastTy.getAsOpaquePtr(),
- CastRange);
- if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof))
- Diag(OpTok, diag::ext_alignof_expr) << OpTok.getIdentifierInfo();
- // If we get here, the operand to the sizeof/alignof was an expression.
- if (!Operand.isInvalid())
- Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),
- ExprKind,
- /*isType=*/false,
- Operand.get(),
- CastRange);
- return Operand;
- }
- /// ParseBuiltinPrimaryExpression
- ///
- /// \verbatim
- /// primary-expression: [C99 6.5.1]
- /// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
- /// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
- /// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
- /// assign-expr ')'
- /// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
- /// [OCL] '__builtin_astype' '(' assignment-expression ',' type-name ')'
- ///
- /// [GNU] offsetof-member-designator:
- /// [GNU] identifier
- /// [GNU] offsetof-member-designator '.' identifier
- /// [GNU] offsetof-member-designator '[' expression ']'
- /// \endverbatim
- ExprResult Parser::ParseBuiltinPrimaryExpression() {
- ExprResult Res;
- const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo();
- tok::TokenKind T = Tok.getKind();
- SourceLocation StartLoc = ConsumeToken(); // Eat the builtin identifier.
- // All of these start with an open paren.
- if (Tok.isNot(tok::l_paren))
- return ExprError(Diag(Tok, diag::err_expected_after) << BuiltinII
- << tok::l_paren);
- BalancedDelimiterTracker PT(*this, tok::l_paren);
- PT.consumeOpen();
- // TODO: Build AST.
- switch (T) {
- default: llvm_unreachable("Not a builtin primary expression!");
- case tok::kw___builtin_va_arg: {
- ExprResult Expr(ParseAssignmentExpression());
- if (ExpectAndConsume(tok::comma)) {
- SkipUntil(tok::r_paren, StopAtSemi);
- Expr = ExprError();
- }
- TypeResult Ty = ParseTypeName();
- if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected) << tok::r_paren;
- Expr = ExprError();
- }
- if (Expr.isInvalid() || Ty.isInvalid())
- Res = ExprError();
- else
- Res = Actions.ActOnVAArg(StartLoc, Expr.get(), Ty.get(), ConsumeParen());
- break;
- }
- case tok::kw___builtin_offsetof: {
- SourceLocation TypeLoc = Tok.getLocation();
- TypeResult Ty = ParseTypeName();
- if (Ty.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- if (ExpectAndConsume(tok::comma)) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- // We must have at least one identifier here.
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected) << tok::identifier;
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- // Keep track of the various subcomponents we see.
- SmallVector<Sema::OffsetOfComponent, 4> Comps;
- Comps.push_back(Sema::OffsetOfComponent());
- Comps.back().isBrackets = false;
- Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
- Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
- // FIXME: This loop leaks the index expressions on error.
- while (1) {
- if (Tok.is(tok::period)) {
- // offsetof-member-designator: offsetof-member-designator '.' identifier
- Comps.push_back(Sema::OffsetOfComponent());
- Comps.back().isBrackets = false;
- Comps.back().LocStart = ConsumeToken();
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected) << tok::identifier;
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
- Comps.back().LocEnd = ConsumeToken();
- } else if (Tok.is(tok::l_square)) {
- if (CheckProhibitedCXX11Attribute())
- return ExprError();
- // offsetof-member-designator: offsetof-member-design '[' expression ']'
- Comps.push_back(Sema::OffsetOfComponent());
- Comps.back().isBrackets = true;
- BalancedDelimiterTracker ST(*this, tok::l_square);
- ST.consumeOpen();
- Comps.back().LocStart = ST.getOpenLocation();
- Res = ParseExpression();
- if (Res.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return Res;
- }
- Comps.back().U.E = Res.get();
- ST.consumeClose();
- Comps.back().LocEnd = ST.getCloseLocation();
- } else {
- if (Tok.isNot(tok::r_paren)) {
- PT.consumeClose();
- Res = ExprError();
- } else if (Ty.isInvalid()) {
- Res = ExprError();
- } else {
- PT.consumeClose();
- Res = Actions.ActOnBuiltinOffsetOf(getCurScope(), StartLoc, TypeLoc,
- Ty.get(), Comps,
- PT.getCloseLocation());
- }
- break;
- }
- }
- break;
- }
- case tok::kw___builtin_choose_expr: {
- ExprResult Cond(ParseAssignmentExpression());
- if (Cond.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return Cond;
- }
- if (ExpectAndConsume(tok::comma)) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- ExprResult Expr1(ParseAssignmentExpression());
- if (Expr1.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return Expr1;
- }
- if (ExpectAndConsume(tok::comma)) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- ExprResult Expr2(ParseAssignmentExpression());
- if (Expr2.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return Expr2;
- }
- if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected) << tok::r_paren;
- return ExprError();
- }
- Res = Actions.ActOnChooseExpr(StartLoc, Cond.get(), Expr1.get(),
- Expr2.get(), ConsumeParen());
- break;
- }
- case tok::kw___builtin_astype: {
- // The first argument is an expression to be converted, followed by a comma.
- ExprResult Expr(ParseAssignmentExpression());
- if (Expr.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- if (ExpectAndConsume(tok::comma)) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- // Second argument is the type to bitcast to.
- TypeResult DestTy = ParseTypeName();
- if (DestTy.isInvalid())
- return ExprError();
- // Attempt to consume the r-paren.
- if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected) << tok::r_paren;
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- Res = Actions.ActOnAsTypeExpr(Expr.get(), DestTy.get(), StartLoc,
- ConsumeParen());
- break;
- }
- case tok::kw___builtin_convertvector: {
- // The first argument is an expression to be converted, followed by a comma.
- ExprResult Expr(ParseAssignmentExpression());
- if (Expr.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- if (ExpectAndConsume(tok::comma)) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- // Second argument is the type to bitcast to.
- TypeResult DestTy = ParseTypeName();
- if (DestTy.isInvalid())
- return ExprError();
- // Attempt to consume the r-paren.
- if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected) << tok::r_paren;
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- Res = Actions.ActOnConvertVectorExpr(Expr.get(), DestTy.get(), StartLoc,
- ConsumeParen());
- break;
- }
- }
- if (Res.isInvalid())
- return ExprError();
- // These can be followed by postfix-expr pieces because they are
- // primary-expressions.
- return ParsePostfixExpressionSuffix(Res.get());
- }
- /// ParseParenExpression - This parses the unit that starts with a '(' token,
- /// based on what is allowed by ExprType. The actual thing parsed is returned
- /// in ExprType. If stopIfCastExpr is true, it will only return the parsed type,
- /// not the parsed cast-expression.
- ///
- /// \verbatim
- /// primary-expression: [C99 6.5.1]
- /// '(' expression ')'
- /// [GNU] '(' compound-statement ')' (if !ParenExprOnly)
- /// postfix-expression: [C99 6.5.2]
- /// '(' type-name ')' '{' initializer-list '}'
- /// '(' type-name ')' '{' initializer-list ',' '}'
- /// cast-expression: [C99 6.5.4]
- /// '(' type-name ')' cast-expression
- /// [ARC] bridged-cast-expression
- /// [ARC] bridged-cast-expression:
- /// (__bridge type-name) cast-expression
- /// (__bridge_transfer type-name) cast-expression
- /// (__bridge_retained type-name) cast-expression
- /// fold-expression: [C++1z]
- /// '(' cast-expression fold-operator '...' ')'
- /// '(' '...' fold-operator cast-expression ')'
- /// '(' cast-expression fold-operator '...'
- /// fold-operator cast-expression ')'
- /// \endverbatim
- ExprResult
- Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
- bool isTypeCast, ParsedType &CastTy,
- SourceLocation &RParenLoc) {
- assert(Tok.is(tok::l_paren) && "Not a paren expr!");
- ColonProtectionRAIIObject ColonProtection(*this, false);
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.consumeOpen())
- return ExprError();
- SourceLocation OpenLoc = T.getOpenLocation();
- ExprResult Result(true);
- bool isAmbiguousTypeId;
- CastTy = nullptr;
- if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(getCurScope(),
- ExprType >= CompoundLiteral? Sema::PCC_ParenthesizedExpression
- : Sema::PCC_Expression);
- cutOffParsing();
- return ExprError();
- }
- // Diagnose use of bridge casts in non-arc mode.
- bool BridgeCast = (getLangOpts().ObjC2 &&
- Tok.isOneOf(tok::kw___bridge,
- tok::kw___bridge_transfer,
- tok::kw___bridge_retained,
- tok::kw___bridge_retain));
- if (BridgeCast && !getLangOpts().ObjCAutoRefCount) {
- if (!TryConsumeToken(tok::kw___bridge)) {
- StringRef BridgeCastName = Tok.getName();
- SourceLocation BridgeKeywordLoc = ConsumeToken();
- if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc))
- Diag(BridgeKeywordLoc, diag::warn_arc_bridge_cast_nonarc)
- << BridgeCastName
- << FixItHint::CreateReplacement(BridgeKeywordLoc, "");
- }
- BridgeCast = false;
- }
- // None of these cases should fall through with an invalid Result
- // unless they've already reported an error.
- if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
- Diag(Tok, diag::ext_gnu_statement_expr);
- if (!getCurScope()->getFnParent() && !getCurScope()->getBlockParent()) {
- Result = ExprError(Diag(OpenLoc, diag::err_stmtexpr_file_scope));
- } else {
- // Find the nearest non-record decl context. Variables declared in a
- // statement expression behave as if they were declared in the enclosing
- // function, block, or other code construct.
- DeclContext *CodeDC = Actions.CurContext;
- while (CodeDC->isRecord() || isa<EnumDecl>(CodeDC)) {
- CodeDC = CodeDC->getParent();
- assert(CodeDC && !CodeDC->isFileContext() &&
- "statement expr not in code context");
- }
- Sema::ContextRAII SavedContext(Actions, CodeDC, /*NewThisContext=*/false);
- Actions.ActOnStartStmtExpr();
- StmtResult Stmt(ParseCompoundStatement(true));
- ExprType = CompoundStmt;
- // If the substmt parsed correctly, build the AST node.
- if (!Stmt.isInvalid()) {
- Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.get(), Tok.getLocation());
- } else {
- Actions.ActOnStmtExprError();
- }
- }
- } else if (ExprType >= CompoundLiteral && BridgeCast) {
- tok::TokenKind tokenKind = Tok.getKind();
- SourceLocation BridgeKeywordLoc = ConsumeToken();
- // Parse an Objective-C ARC ownership cast expression.
- ObjCBridgeCastKind Kind;
- if (tokenKind == tok::kw___bridge)
- Kind = OBC_Bridge;
- else if (tokenKind == tok::kw___bridge_transfer)
- Kind = OBC_BridgeTransfer;
- else if (tokenKind == tok::kw___bridge_retained)
- Kind = OBC_BridgeRetained;
- else {
- // As a hopefully temporary workaround, allow __bridge_retain as
- // a synonym for __bridge_retained, but only in system headers.
- assert(tokenKind == tok::kw___bridge_retain);
- Kind = OBC_BridgeRetained;
- if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc))
- Diag(BridgeKeywordLoc, diag::err_arc_bridge_retain)
- << FixItHint::CreateReplacement(BridgeKeywordLoc,
- "__bridge_retained");
- }
- TypeResult Ty = ParseTypeName();
- T.consumeClose();
- ColonProtection.restore();
- RParenLoc = T.getCloseLocation();
- ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false);
- if (Ty.isInvalid() || SubExpr.isInvalid())
- return ExprError();
- return Actions.ActOnObjCBridgedCast(getCurScope(), OpenLoc, Kind,
- BridgeKeywordLoc, Ty.get(),
- RParenLoc, SubExpr.get());
- } else if (ExprType >= CompoundLiteral &&
- isTypeIdInParens(isAmbiguousTypeId)) {
- // Otherwise, this is a compound literal expression or cast expression.
- // In C++, if the type-id is ambiguous we disambiguate based on context.
- // If stopIfCastExpr is true the context is a typeof/sizeof/alignof
- // in which case we should treat it as type-id.
- // if stopIfCastExpr is false, we need to determine the context past the
- // parens, so we defer to ParseCXXAmbiguousParenExpression for that.
- if (isAmbiguousTypeId && !stopIfCastExpr) {
- ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T,
- ColonProtection);
- RParenLoc = T.getCloseLocation();
- return res;
- }
- // Parse the type declarator.
- DeclSpec DS(AttrFactory);
- ParseSpecifierQualifierList(DS);
- Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
- ParseDeclarator(DeclaratorInfo);
- // If our type is followed by an identifier and either ':' or ']', then
- // this is probably an Objective-C message send where the leading '[' is
- // missing. Recover as if that were the case.
- if (!DeclaratorInfo.isInvalidType() && Tok.is(tok::identifier) &&
- !InMessageExpression && getLangOpts().ObjC1 &&
- (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {
- TypeResult Ty;
- {
- InMessageExpressionRAIIObject InMessage(*this, false);
- Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
- }
- Result = ParseObjCMessageExpressionBody(SourceLocation(),
- SourceLocation(),
- Ty.get(), nullptr);
- } else {
- // Match the ')'.
- T.consumeClose();
- ColonProtection.restore();
- RParenLoc = T.getCloseLocation();
- if (Tok.is(tok::l_brace)) {
- ExprType = CompoundLiteral;
- TypeResult Ty;
- {
- InMessageExpressionRAIIObject InMessage(*this, false);
- Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
- }
- return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);
- }
- if (Tok.is(tok::l_paren)) {
- // This could be OpenCL vector Literals
- if (getLangOpts().OpenCL)
- {
- TypeResult Ty;
- {
- InMessageExpressionRAIIObject InMessage(*this, false);
- Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
- }
- if(Ty.isInvalid())
- {
- return ExprError();
- }
- QualType QT = Ty.get().get().getCanonicalType();
- if (QT->isVectorType())
- {
- // We parsed '(' vector-type-name ')' followed by '('
- // Parse the cast-expression that follows it next.
- // isVectorLiteral = true will make sure we don't parse any
- // Postfix expression yet
- Result = ParseCastExpression(/*isUnaryExpression=*/false,
- /*isAddressOfOperand=*/false,
- /*isTypeCast=*/IsTypeCast,
- /*isVectorLiteral=*/true);
- if (!Result.isInvalid()) {
- Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc,
- DeclaratorInfo, CastTy,
- RParenLoc, Result.get());
- }
- // After we performed the cast we can check for postfix-expr pieces.
- if (!Result.isInvalid()) {
- Result = ParsePostfixExpressionSuffix(Result);
- }
- return Result;
- }
- }
- }
- if (ExprType == CastExpr) {
- // We parsed '(' type-name ')' and the thing after it wasn't a '{'.
- if (DeclaratorInfo.isInvalidType())
- return ExprError();
- // Note that this doesn't parse the subsequent cast-expression, it just
- // returns the parsed type to the callee.
- if (stopIfCastExpr) {
- TypeResult Ty;
- {
- InMessageExpressionRAIIObject InMessage(*this, false);
- Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
- }
- CastTy = Ty.get();
- return ExprResult();
- }
- // Reject the cast of super idiom in ObjC.
- if (Tok.is(tok::identifier) && getLangOpts().ObjC1 &&
- Tok.getIdentifierInfo() == Ident_super &&
- getCurScope()->isInObjcMethodScope() &&
- GetLookAheadToken(1).isNot(tok::period)) {
- Diag(Tok.getLocation(), diag::err_illegal_super_cast)
- << SourceRange(OpenLoc, RParenLoc);
- return ExprError();
- }
- // Parse the cast-expression that follows it next.
- // TODO: For cast expression with CastTy.
- Result = ParseCastExpression(/*isUnaryExpression=*/false,
- /*isAddressOfOperand=*/false,
- /*isTypeCast=*/IsTypeCast);
- if (!Result.isInvalid()) {
- Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc,
- DeclaratorInfo, CastTy,
- RParenLoc, Result.get());
- }
- return Result;
- }
- Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
- return ExprError();
- }
- } else if (ExprType >= FoldExpr && Tok.is(tok::ellipsis) &&
- isFoldOperator(NextToken().getKind())) {
- ExprType = FoldExpr;
- return ParseFoldExpression(ExprResult(), T);
- } else if (isTypeCast) {
- // Parse the expression-list.
- InMessageExpressionRAIIObject InMessage(*this, false);
- ExprVector ArgExprs;
- CommaLocsTy CommaLocs;
- if (!ParseSimpleExpressionList(ArgExprs, CommaLocs)) {
- // 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 &&
- isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {
- ExprType = FoldExpr;
- return ParseFoldExpression(ArgExprs[0], T);
- }
- ExprType = SimpleExpr;
- Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
- ArgExprs);
- }
- } else {
- InMessageExpressionRAIIObject InMessage(*this, false);
- Result = ParseExpression(MaybeTypeCast);
- if (!getLangOpts().CPlusPlus && MaybeTypeCast && Result.isUsable()) {
- // Correct typos in non-C++ code earlier so that implicit-cast-like
- // expressions are parsed correctly.
- Result = Actions.CorrectDelayedTyposInExpr(Result);
- }
- if (ExprType >= FoldExpr && isFoldOperator(Tok.getKind()) &&
- NextToken().is(tok::ellipsis)) {
- ExprType = FoldExpr;
- return ParseFoldExpression(Result, T);
- }
- ExprType = SimpleExpr;
- // Don't build a paren expression unless we actually match a ')'.
- if (!Result.isInvalid() && Tok.is(tok::r_paren))
- Result =
- Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.get());
- }
- // Match the ')'.
- if (Result.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- T.consumeClose();
- RParenLoc = T.getCloseLocation();
- return Result;
- }
- /// ParseCompoundLiteralExpression - We have parsed the parenthesized type-name
- /// and we are at the left brace.
- ///
- /// \verbatim
- /// postfix-expression: [C99 6.5.2]
- /// '(' type-name ')' '{' initializer-list '}'
- /// '(' type-name ')' '{' initializer-list ',' '}'
- /// \endverbatim
- ExprResult
- Parser::ParseCompoundLiteralExpression(ParsedType Ty,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
- assert(Tok.is(tok::l_brace) && "Not a compound literal!");
- if (!getLangOpts().C99) // Compound literals don't exist in C90.
- Diag(LParenLoc, diag::ext_c99_compound_literal);
- ExprResult Result = ParseInitializer();
- if (!Result.isInvalid() && Ty)
- return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.get());
- return Result;
- }
- /// ParseStringLiteralExpression - This handles the various token types that
- /// form string literals, and also handles string concatenation [C99 5.1.1.2,
- /// translation phase #6].
- ///
- /// \verbatim
- /// primary-expression: [C99 6.5.1]
- /// string-literal
- /// \verbatim
- ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral) {
- assert(isTokenStringLiteral() && "Not a string literal!");
- // String concat. Note that keywords like __func__ and __FUNCTION__ are not
- // considered to be strings for concatenation purposes.
- SmallVector<Token, 4> StringToks;
- do {
- StringToks.push_back(Tok);
- ConsumeStringToken();
- } while (isTokenStringLiteral());
- // Pass the set of string tokens, ready for concatenation, to the actions.
- return Actions.ActOnStringLiteral(StringToks,
- AllowUserDefinedLiteral ? getCurScope()
- : nullptr);
- }
- /// ParseGenericSelectionExpression - Parse a C11 generic-selection
- /// [C11 6.5.1.1].
- ///
- /// \verbatim
- /// generic-selection:
- /// _Generic ( assignment-expression , generic-assoc-list )
- /// generic-assoc-list:
- /// generic-association
- /// generic-assoc-list , generic-association
- /// generic-association:
- /// type-name : assignment-expression
- /// default : assignment-expression
- /// \endverbatim
- ExprResult Parser::ParseGenericSelectionExpression() {
- assert(Tok.is(tok::kw__Generic) && "_Generic keyword expected");
- SourceLocation KeyLoc = ConsumeToken();
- if (!getLangOpts().C11)
- Diag(KeyLoc, diag::ext_c11_generic_selection);
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume())
- return ExprError();
- ExprResult ControllingExpr;
- {
- // C11 6.5.1.1p3 "The controlling expression of a generic selection is
- // not evaluated."
- EnterExpressionEvaluationContext Unevaluated(
- Actions, Sema::ExpressionEvaluationContext::Unevaluated);
- ControllingExpr =
- Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
- if (ControllingExpr.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- }
- if (ExpectAndConsume(tok::comma)) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- SourceLocation DefaultLoc;
- TypeVector Types;
- ExprVector Exprs;
- do {
- ParsedType Ty;
- if (Tok.is(tok::kw_default)) {
- // C11 6.5.1.1p2 "A generic selection shall have no more than one default
- // generic association."
- if (!DefaultLoc.isInvalid()) {
- Diag(Tok, diag::err_duplicate_default_assoc);
- Diag(DefaultLoc, diag::note_previous_default_assoc);
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- DefaultLoc = ConsumeToken();
- Ty = nullptr;
- } else {
- ColonProtectionRAIIObject X(*this);
- TypeResult TR = ParseTypeName();
- if (TR.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- Ty = TR.get();
- }
- Types.push_back(Ty);
- if (ExpectAndConsume(tok::colon)) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- // FIXME: These expressions should be parsed in a potentially potentially
- // evaluated context.
- ExprResult ER(
- Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
- if (ER.isInvalid()) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- Exprs.push_back(ER.get());
- } while (TryConsumeToken(tok::comma));
- T.consumeClose();
- if (T.getCloseLocation().isInvalid())
- return ExprError();
- return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc,
- T.getCloseLocation(),
- ControllingExpr.get(),
- Types, Exprs);
- }
- /// Parse A C++1z fold-expression after the opening paren and optional
- /// left-hand-side expression.
- ///
- /// \verbatim
- /// fold-expression:
- /// ( cast-expression fold-operator ... )
- /// ( ... fold-operator cast-expression )
- /// ( cast-expression fold-operator ... fold-operator cast-expression )
- ExprResult Parser::ParseFoldExpression(ExprResult LHS,
- BalancedDelimiterTracker &T) {
- if (LHS.isInvalid()) {
- T.skipToEnd();
- return true;
- }
- tok::TokenKind Kind = tok::unknown;
- SourceLocation FirstOpLoc;
- if (LHS.isUsable()) {
- Kind = Tok.getKind();
- assert(isFoldOperator(Kind) && "missing fold-operator");
- FirstOpLoc = ConsumeToken();
- }
- assert(Tok.is(tok::ellipsis) && "not a fold-expression");
- SourceLocation EllipsisLoc = ConsumeToken();
- ExprResult RHS;
- if (Tok.isNot(tok::r_paren)) {
- if (!isFoldOperator(Tok.getKind()))
- return Diag(Tok.getLocation(), diag::err_expected_fold_operator);
- if (Kind != tok::unknown && Tok.getKind() != Kind)
- Diag(Tok.getLocation(), diag::err_fold_operator_mismatch)
- << SourceRange(FirstOpLoc);
- Kind = Tok.getKind();
- ConsumeToken();
- RHS = ParseExpression();
- if (RHS.isInvalid()) {
- T.skipToEnd();
- return true;
- }
- }
- Diag(EllipsisLoc, getLangOpts().CPlusPlus17
- ? diag::warn_cxx14_compat_fold_expression
- : diag::ext_fold_expression);
- T.consumeClose();
- return Actions.ActOnCXXFoldExpr(T.getOpenLocation(), LHS.get(), Kind,
- EllipsisLoc, RHS.get(), T.getCloseLocation());
- }
- /// ParseExpressionList - Used for C/C++ (argument-)expression-list.
- ///
- /// \verbatim
- /// argument-expression-list:
- /// assignment-expression
- /// argument-expression-list , assignment-expression
- ///
- /// [C++] expression-list:
- /// [C++] assignment-expression
- /// [C++] expression-list , assignment-expression
- ///
- /// [C++0x] expression-list:
- /// [C++0x] initializer-list
- ///
- /// [C++0x] initializer-list
- /// [C++0x] initializer-clause ...[opt]
- /// [C++0x] initializer-list , initializer-clause ...[opt]
- ///
- /// [C++0x] initializer-clause:
- /// [C++0x] assignment-expression
- /// [C++0x] braced-init-list
- /// \endverbatim
- bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
- SmallVectorImpl<SourceLocation> &CommaLocs,
- llvm::function_ref<void()> Completer) {
- bool SawError = false;
- while (1) {
- if (Tok.is(tok::code_completion)) {
- if (Completer)
- Completer();
- else
- Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
- cutOffParsing();
- return true;
- }
- ExprResult Expr;
- if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
- Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
- Expr = ParseBraceInitializer();
- } else
- Expr = ParseAssignmentExpression();
- if (Tok.is(tok::ellipsis))
- Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
- if (Expr.isInvalid()) {
- SkipUntil(tok::comma, tok::r_paren, StopBeforeMatch);
- SawError = true;
- } else {
- Exprs.push_back(Expr.get());
- }
- if (Tok.isNot(tok::comma))
- break;
- // Move to the next argument, remember where the comma was.
- Token Comma = Tok;
- CommaLocs.push_back(ConsumeToken());
- checkPotentialAngleBracketDelimiter(Comma);
- }
- if (SawError) {
- // Ensure typos get diagnosed when errors were encountered while parsing the
- // expression list.
- for (auto &E : Exprs) {
- ExprResult Expr = Actions.CorrectDelayedTyposInExpr(E);
- if (Expr.isUsable()) E = Expr.get();
- }
- }
- return SawError;
- }
- /// ParseSimpleExpressionList - A simple comma-separated list of expressions,
- /// used for misc language extensions.
- ///
- /// \verbatim
- /// simple-expression-list:
- /// assignment-expression
- /// simple-expression-list , assignment-expression
- /// \endverbatim
- bool
- Parser::ParseSimpleExpressionList(SmallVectorImpl<Expr*> &Exprs,
- SmallVectorImpl<SourceLocation> &CommaLocs) {
- while (1) {
- ExprResult Expr = ParseAssignmentExpression();
- if (Expr.isInvalid())
- return true;
- Exprs.push_back(Expr.get());
- if (Tok.isNot(tok::comma))
- return false;
- // Move to the next argument, remember where the comma was.
- Token Comma = Tok;
- CommaLocs.push_back(ConsumeToken());
- checkPotentialAngleBracketDelimiter(Comma);
- }
- }
- /// ParseBlockId - Parse a block-id, which roughly looks like int (int x).
- ///
- /// \verbatim
- /// [clang] block-id:
- /// [clang] specifier-qualifier-list block-declarator
- /// \endverbatim
- void Parser::ParseBlockId(SourceLocation CaretLoc) {
- if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
- return cutOffParsing();
- }
- // Parse the specifier-qualifier-list piece.
- DeclSpec DS(AttrFactory);
- ParseSpecifierQualifierList(DS);
- // Parse the block-declarator.
- Declarator DeclaratorInfo(DS, DeclaratorContext::BlockLiteralContext);
- DeclaratorInfo.setFunctionDefinitionKind(FDK_Definition);
- ParseDeclarator(DeclaratorInfo);
- MaybeParseGNUAttributes(DeclaratorInfo);
- // Inform sema that we are starting a block.
- Actions.ActOnBlockArguments(CaretLoc, DeclaratorInfo, getCurScope());
- }
- /// ParseBlockLiteralExpression - Parse a block literal, which roughly looks
- /// like ^(int x){ return x+1; }
- ///
- /// \verbatim
- /// block-literal:
- /// [clang] '^' block-args[opt] compound-statement
- /// [clang] '^' block-id compound-statement
- /// [clang] block-args:
- /// [clang] '(' parameter-list ')'
- /// \endverbatim
- ExprResult Parser::ParseBlockLiteralExpression() {
- assert(Tok.is(tok::caret) && "block literal starts with ^");
- SourceLocation CaretLoc = ConsumeToken();
- PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), CaretLoc,
- "block literal parsing");
- // Enter a scope to hold everything within the block. This includes the
- // argument decls, decls within the compound expression, etc. This also
- // allows determining whether a variable reference inside the block is
- // within or outside of the block.
- ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope |
- Scope::CompoundStmtScope | Scope::DeclScope);
- // Inform sema that we are starting a block.
- Actions.ActOnBlockStart(CaretLoc, getCurScope());
- // Parse the return type if present.
- DeclSpec DS(AttrFactory);
- Declarator ParamInfo(DS, DeclaratorContext::BlockLiteralContext);
- ParamInfo.setFunctionDefinitionKind(FDK_Definition);
- // FIXME: Since the return type isn't actually parsed, it can't be used to
- // fill ParamInfo with an initial valid range, so do it manually.
- ParamInfo.SetSourceRange(SourceRange(Tok.getLocation(), Tok.getLocation()));
- // If this block has arguments, parse them. There is no ambiguity here with
- // the expression case, because the expression case requires a parameter list.
- if (Tok.is(tok::l_paren)) {
- ParseParenDeclarator(ParamInfo);
- // Parse the pieces after the identifier as if we had "int(...)".
- // SetIdentifier sets the source range end, but in this case we're past
- // that location.
- SourceLocation Tmp = ParamInfo.getSourceRange().getEnd();
- ParamInfo.SetIdentifier(nullptr, CaretLoc);
- ParamInfo.SetRangeEnd(Tmp);
- if (ParamInfo.isInvalidType()) {
- // If there was an error parsing the arguments, they may have
- // tried to use ^(x+y) which requires an argument list. Just
- // skip the whole block literal.
- Actions.ActOnBlockError(CaretLoc, getCurScope());
- return ExprError();
- }
- MaybeParseGNUAttributes(ParamInfo);
- // Inform sema that we are starting a block.
- Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());
- } else if (!Tok.is(tok::l_brace)) {
- ParseBlockId(CaretLoc);
- } else {
- // Otherwise, pretend we saw (void).
- SourceLocation NoLoc;
- ParamInfo.AddTypeInfo(
- DeclaratorChunk::getFunction(/*HasProto=*/true,
- /*IsAmbiguous=*/false,
- /*RParenLoc=*/NoLoc,
- /*ArgInfo=*/nullptr,
- /*NumArgs=*/0,
- /*EllipsisLoc=*/NoLoc,
- /*RParenLoc=*/NoLoc,
- /*TypeQuals=*/0,
- /*RefQualifierIsLvalueRef=*/true,
- /*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*RestrictQualifierLoc=*/NoLoc,
- /*MutableLoc=*/NoLoc, EST_None,
- /*ESpecRange=*/SourceRange(),
- /*Exceptions=*/nullptr,
- /*ExceptionRanges=*/nullptr,
- /*NumExceptions=*/0,
- /*NoexceptExpr=*/nullptr,
- /*ExceptionSpecTokens=*/nullptr,
- /*DeclsInPrototype=*/None, CaretLoc,
- CaretLoc, ParamInfo),
- CaretLoc);
- MaybeParseGNUAttributes(ParamInfo);
- // Inform sema that we are starting a block.
- Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());
- }
- ExprResult Result(true);
- if (!Tok.is(tok::l_brace)) {
- // Saw something like: ^expr
- Diag(Tok, diag::err_expected_expression);
- Actions.ActOnBlockError(CaretLoc, getCurScope());
- return ExprError();
- }
- StmtResult Stmt(ParseCompoundStatementBody());
- BlockScope.Exit();
- if (!Stmt.isInvalid())
- Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.get(), getCurScope());
- else
- Actions.ActOnBlockError(CaretLoc, getCurScope());
- return Result;
- }
- /// ParseObjCBoolLiteral - This handles the objective-c Boolean literals.
- ///
- /// '__objc_yes'
- /// '__objc_no'
- ExprResult Parser::ParseObjCBoolLiteral() {
- tok::TokenKind Kind = Tok.getKind();
- return Actions.ActOnObjCBoolLiteral(ConsumeToken(), Kind);
- }
- /// Validate availability spec list, emitting diagnostics if necessary. Returns
- /// true if invalid.
- static bool CheckAvailabilitySpecList(Parser &P,
- ArrayRef<AvailabilitySpec> AvailSpecs) {
- llvm::SmallSet<StringRef, 4> Platforms;
- bool HasOtherPlatformSpec = false;
- bool Valid = true;
- for (const auto &Spec : AvailSpecs) {
- if (Spec.isOtherPlatformSpec()) {
- if (HasOtherPlatformSpec) {
- P.Diag(Spec.getBeginLoc(), diag::err_availability_query_repeated_star);
- Valid = false;
- }
- HasOtherPlatformSpec = true;
- continue;
- }
- bool Inserted = Platforms.insert(Spec.getPlatform()).second;
- if (!Inserted) {
- // Rule out multiple version specs referring to the same platform.
- // For example, we emit an error for:
- // @available(macos 10.10, macos 10.11, *)
- StringRef Platform = Spec.getPlatform();
- P.Diag(Spec.getBeginLoc(), diag::err_availability_query_repeated_platform)
- << Spec.getEndLoc() << Platform;
- Valid = false;
- }
- }
- if (!HasOtherPlatformSpec) {
- SourceLocation InsertWildcardLoc = AvailSpecs.back().getEndLoc();
- P.Diag(InsertWildcardLoc, diag::err_availability_query_wildcard_required)
- << FixItHint::CreateInsertion(InsertWildcardLoc, ", *");
- return true;
- }
- return !Valid;
- }
- /// Parse availability query specification.
- ///
- /// availability-spec:
- /// '*'
- /// identifier version-tuple
- Optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() {
- if (Tok.is(tok::star)) {
- return AvailabilitySpec(ConsumeToken());
- } else {
- // Parse the platform name.
- if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteAvailabilityPlatformName();
- cutOffParsing();
- return None;
- }
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_avail_query_expected_platform_name);
- return None;
- }
- IdentifierLoc *PlatformIdentifier = ParseIdentifierLoc();
- SourceRange VersionRange;
- VersionTuple Version = ParseVersionTuple(VersionRange);
- if (Version.empty())
- return None;
- StringRef GivenPlatform = PlatformIdentifier->Ident->getName();
- StringRef Platform =
- AvailabilityAttr::canonicalizePlatformName(GivenPlatform);
- if (AvailabilityAttr::getPrettyPlatformName(Platform).empty()) {
- Diag(PlatformIdentifier->Loc,
- diag::err_avail_query_unrecognized_platform_name)
- << GivenPlatform;
- return None;
- }
- return AvailabilitySpec(Version, Platform, PlatformIdentifier->Loc,
- VersionRange.getEnd());
- }
- }
- ExprResult Parser::ParseAvailabilityCheckExpr(SourceLocation BeginLoc) {
- assert(Tok.is(tok::kw___builtin_available) ||
- Tok.isObjCAtKeyword(tok::objc_available));
- // Eat the available or __builtin_available.
- ConsumeToken();
- BalancedDelimiterTracker Parens(*this, tok::l_paren);
- if (Parens.expectAndConsume())
- return ExprError();
- SmallVector<AvailabilitySpec, 4> AvailSpecs;
- bool HasError = false;
- while (true) {
- Optional<AvailabilitySpec> Spec = ParseAvailabilitySpec();
- if (!Spec)
- HasError = true;
- else
- AvailSpecs.push_back(*Spec);
- if (!TryConsumeToken(tok::comma))
- break;
- }
- if (HasError) {
- SkipUntil(tok::r_paren, StopAtSemi);
- return ExprError();
- }
- CheckAvailabilitySpecList(*this, AvailSpecs);
- if (Parens.consumeClose())
- return ExprError();
- return Actions.ActOnObjCAvailabilityCheckExpr(AvailSpecs, BeginLoc,
- Parens.getCloseLocation());
- }
|