12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037 |
- //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements the language specific #pragma handlers.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/AST/ASTContext.h"
- #include "clang/Basic/PragmaKinds.h"
- #include "clang/Basic/TargetInfo.h"
- #include "clang/Lex/Preprocessor.h"
- #include "clang/Lex/Token.h"
- #include "clang/Parse/LoopHint.h"
- #include "clang/Parse/ParseDiagnostic.h"
- #include "clang/Parse/Parser.h"
- #include "clang/Parse/RAIIObjectsForParser.h"
- #include "clang/Sema/Scope.h"
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/ADT/StringSwitch.h"
- #include <optional>
- using namespace clang;
- namespace {
- struct PragmaAlignHandler : public PragmaHandler {
- explicit PragmaAlignHandler() : PragmaHandler("align") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaGCCVisibilityHandler : public PragmaHandler {
- explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaOptionsHandler : public PragmaHandler {
- explicit PragmaOptionsHandler() : PragmaHandler("options") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaPackHandler : public PragmaHandler {
- explicit PragmaPackHandler() : PragmaHandler("pack") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaClangSectionHandler : public PragmaHandler {
- explicit PragmaClangSectionHandler(Sema &S)
- : PragmaHandler("section"), Actions(S) {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- private:
- Sema &Actions;
- };
- struct PragmaMSStructHandler : public PragmaHandler {
- explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaUnusedHandler : public PragmaHandler {
- PragmaUnusedHandler() : PragmaHandler("unused") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaWeakHandler : public PragmaHandler {
- explicit PragmaWeakHandler() : PragmaHandler("weak") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaRedefineExtnameHandler : public PragmaHandler {
- explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaOpenCLExtensionHandler : public PragmaHandler {
- PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaFPContractHandler : public PragmaHandler {
- PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- // Pragma STDC implementations.
- /// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
- struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
- PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &Tok) override {
- Token PragmaName = Tok;
- if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
- << PragmaName.getIdentifierInfo()->getName();
- return;
- }
- tok::OnOffSwitch OOS;
- if (PP.LexOnOffSwitch(OOS))
- return;
- MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
- 1);
- Toks[0].startToken();
- Toks[0].setKind(tok::annot_pragma_fenv_access);
- Toks[0].setLocation(Tok.getLocation());
- Toks[0].setAnnotationEndLoc(Tok.getLocation());
- Toks[0].setAnnotationValue(reinterpret_cast<void*>(
- static_cast<uintptr_t>(OOS)));
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- }
- };
- /// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
- struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
- PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &Tok) override {
- tok::OnOffSwitch OOS;
- PP.LexOnOffSwitch(OOS);
- }
- };
- /// Handler for "\#pragma STDC FENV_ROUND ...".
- struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler {
- PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &Tok) override;
- };
- /// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
- struct PragmaSTDC_UnknownHandler : public PragmaHandler {
- PragmaSTDC_UnknownHandler() = default;
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &UnknownTok) override {
- // C99 6.10.6p2, unknown forms are not allowed.
- PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
- }
- };
- struct PragmaFPHandler : public PragmaHandler {
- PragmaFPHandler() : PragmaHandler("fp") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaNoOpenMPHandler : public PragmaHandler {
- PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaOpenMPHandler : public PragmaHandler {
- PragmaOpenMPHandler() : PragmaHandler("omp") { }
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- /// PragmaCommentHandler - "\#pragma comment ...".
- struct PragmaCommentHandler : public PragmaHandler {
- PragmaCommentHandler(Sema &Actions)
- : PragmaHandler("comment"), Actions(Actions) {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- private:
- Sema &Actions;
- };
- struct PragmaDetectMismatchHandler : public PragmaHandler {
- PragmaDetectMismatchHandler(Sema &Actions)
- : PragmaHandler("detect_mismatch"), Actions(Actions) {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- private:
- Sema &Actions;
- };
- struct PragmaFloatControlHandler : public PragmaHandler {
- PragmaFloatControlHandler(Sema &Actions)
- : PragmaHandler("float_control") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaMSPointersToMembers : public PragmaHandler {
- explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaMSVtorDisp : public PragmaHandler {
- explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaMSPragma : public PragmaHandler {
- explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
- struct PragmaOptimizeHandler : public PragmaHandler {
- PragmaOptimizeHandler(Sema &S)
- : PragmaHandler("optimize"), Actions(S) {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- private:
- Sema &Actions;
- };
- struct PragmaLoopHintHandler : public PragmaHandler {
- PragmaLoopHintHandler() : PragmaHandler("loop") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaUnrollHintHandler : public PragmaHandler {
- PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
- PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
- };
- struct PragmaMSIntrinsicHandler : public PragmaHandler {
- PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- // "\#pragma fenv_access (on)".
- struct PragmaMSFenvAccessHandler : public PragmaHandler {
- PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override {
- StringRef PragmaName = FirstToken.getIdentifierInfo()->getName();
- if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
- PP.Diag(FirstToken.getLocation(), diag::warn_pragma_fp_ignored)
- << PragmaName;
- return;
- }
- Token Tok;
- PP.Lex(Tok);
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
- << PragmaName;
- return;
- }
- PP.Lex(Tok); // Consume the l_paren.
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
- return;
- }
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- tok::OnOffSwitch OOS;
- if (II->isStr("on")) {
- OOS = tok::OOS_ON;
- PP.Lex(Tok);
- } else if (II->isStr("off")) {
- OOS = tok::OOS_OFF;
- PP.Lex(Tok);
- } else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
- return;
- }
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
- << PragmaName;
- return;
- }
- PP.Lex(Tok); // Consume the r_paren.
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << PragmaName;
- return;
- }
- MutableArrayRef<Token> Toks(
- PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
- Toks[0].startToken();
- Toks[0].setKind(tok::annot_pragma_fenv_access_ms);
- Toks[0].setLocation(FirstToken.getLocation());
- Toks[0].setAnnotationEndLoc(Tok.getLocation());
- Toks[0].setAnnotationValue(
- reinterpret_cast<void*>(static_cast<uintptr_t>(OOS)));
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- }
- };
- struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
- PragmaForceCUDAHostDeviceHandler(Sema &Actions)
- : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- private:
- Sema &Actions;
- };
- /// PragmaAttributeHandler - "\#pragma clang attribute ...".
- struct PragmaAttributeHandler : public PragmaHandler {
- PragmaAttributeHandler(AttributeFactory &AttrFactory)
- : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- /// A pool of attributes that were parsed in \#pragma clang attribute.
- ParsedAttributes AttributesForPragmaAttribute;
- };
- struct PragmaMaxTokensHereHandler : public PragmaHandler {
- PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaMaxTokensTotalHandler : public PragmaHandler {
- PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- };
- struct PragmaRISCVHandler : public PragmaHandler {
- PragmaRISCVHandler(Sema &Actions)
- : PragmaHandler("riscv"), Actions(Actions) {}
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &FirstToken) override;
- private:
- Sema &Actions;
- };
- void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) {
- for (auto &T : Toks)
- T.setFlag(clang::Token::IsReinjected);
- }
- } // end namespace
- void Parser::initializePragmaHandlers() {
- AlignHandler = std::make_unique<PragmaAlignHandler>();
- PP.AddPragmaHandler(AlignHandler.get());
- GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
- PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
- OptionsHandler = std::make_unique<PragmaOptionsHandler>();
- PP.AddPragmaHandler(OptionsHandler.get());
- PackHandler = std::make_unique<PragmaPackHandler>();
- PP.AddPragmaHandler(PackHandler.get());
- MSStructHandler = std::make_unique<PragmaMSStructHandler>();
- PP.AddPragmaHandler(MSStructHandler.get());
- UnusedHandler = std::make_unique<PragmaUnusedHandler>();
- PP.AddPragmaHandler(UnusedHandler.get());
- WeakHandler = std::make_unique<PragmaWeakHandler>();
- PP.AddPragmaHandler(WeakHandler.get());
- RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
- PP.AddPragmaHandler(RedefineExtnameHandler.get());
- FPContractHandler = std::make_unique<PragmaFPContractHandler>();
- PP.AddPragmaHandler("STDC", FPContractHandler.get());
- STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
- PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get());
- STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>();
- PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get());
- STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
- PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
- STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
- PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
- PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
- PP.AddPragmaHandler("clang", PCSectionHandler.get());
- if (getLangOpts().OpenCL) {
- OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
- PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
- PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
- }
- if (getLangOpts().OpenMP)
- OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
- else
- OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
- PP.AddPragmaHandler(OpenMPHandler.get());
- if (getLangOpts().MicrosoftExt ||
- getTargetInfo().getTriple().isOSBinFormatELF()) {
- MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
- PP.AddPragmaHandler(MSCommentHandler.get());
- }
- FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
- PP.AddPragmaHandler(FloatControlHandler.get());
- if (getLangOpts().MicrosoftExt) {
- MSDetectMismatchHandler =
- std::make_unique<PragmaDetectMismatchHandler>(Actions);
- PP.AddPragmaHandler(MSDetectMismatchHandler.get());
- MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
- PP.AddPragmaHandler(MSPointersToMembers.get());
- MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
- PP.AddPragmaHandler(MSVtorDisp.get());
- MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
- PP.AddPragmaHandler(MSInitSeg.get());
- MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
- PP.AddPragmaHandler(MSDataSeg.get());
- MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
- PP.AddPragmaHandler(MSBSSSeg.get());
- MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
- PP.AddPragmaHandler(MSConstSeg.get());
- MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
- PP.AddPragmaHandler(MSCodeSeg.get());
- MSSection = std::make_unique<PragmaMSPragma>("section");
- PP.AddPragmaHandler(MSSection.get());
- MSStrictGuardStackCheck =
- std::make_unique<PragmaMSPragma>("strict_gs_check");
- PP.AddPragmaHandler(MSStrictGuardStackCheck.get());
- MSFunction = std::make_unique<PragmaMSPragma>("function");
- PP.AddPragmaHandler(MSFunction.get());
- MSAllocText = std::make_unique<PragmaMSPragma>("alloc_text");
- PP.AddPragmaHandler(MSAllocText.get());
- MSOptimize = std::make_unique<PragmaMSPragma>("optimize");
- PP.AddPragmaHandler(MSOptimize.get());
- MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
- PP.AddPragmaHandler(MSRuntimeChecks.get());
- MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
- PP.AddPragmaHandler(MSIntrinsic.get());
- MSFenvAccess = std::make_unique<PragmaMSFenvAccessHandler>();
- PP.AddPragmaHandler(MSFenvAccess.get());
- }
- if (getLangOpts().CUDA) {
- CUDAForceHostDeviceHandler =
- std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
- PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
- }
- OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
- PP.AddPragmaHandler("clang", OptimizeHandler.get());
- LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
- PP.AddPragmaHandler("clang", LoopHintHandler.get());
- UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
- PP.AddPragmaHandler(UnrollHintHandler.get());
- PP.AddPragmaHandler("GCC", UnrollHintHandler.get());
- NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
- PP.AddPragmaHandler(NoUnrollHintHandler.get());
- PP.AddPragmaHandler("GCC", NoUnrollHintHandler.get());
- UnrollAndJamHintHandler =
- std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
- PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
- NoUnrollAndJamHintHandler =
- std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
- PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
- FPHandler = std::make_unique<PragmaFPHandler>();
- PP.AddPragmaHandler("clang", FPHandler.get());
- AttributePragmaHandler =
- std::make_unique<PragmaAttributeHandler>(AttrFactory);
- PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
- MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
- PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
- MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
- PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
- if (getTargetInfo().getTriple().isRISCV()) {
- RISCVPragmaHandler = std::make_unique<PragmaRISCVHandler>(Actions);
- PP.AddPragmaHandler("clang", RISCVPragmaHandler.get());
- }
- }
- void Parser::resetPragmaHandlers() {
- // Remove the pragma handlers we installed.
- PP.RemovePragmaHandler(AlignHandler.get());
- AlignHandler.reset();
- PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
- GCCVisibilityHandler.reset();
- PP.RemovePragmaHandler(OptionsHandler.get());
- OptionsHandler.reset();
- PP.RemovePragmaHandler(PackHandler.get());
- PackHandler.reset();
- PP.RemovePragmaHandler(MSStructHandler.get());
- MSStructHandler.reset();
- PP.RemovePragmaHandler(UnusedHandler.get());
- UnusedHandler.reset();
- PP.RemovePragmaHandler(WeakHandler.get());
- WeakHandler.reset();
- PP.RemovePragmaHandler(RedefineExtnameHandler.get());
- RedefineExtnameHandler.reset();
- if (getLangOpts().OpenCL) {
- PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
- OpenCLExtensionHandler.reset();
- PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
- }
- PP.RemovePragmaHandler(OpenMPHandler.get());
- OpenMPHandler.reset();
- if (getLangOpts().MicrosoftExt ||
- getTargetInfo().getTriple().isOSBinFormatELF()) {
- PP.RemovePragmaHandler(MSCommentHandler.get());
- MSCommentHandler.reset();
- }
- PP.RemovePragmaHandler("clang", PCSectionHandler.get());
- PCSectionHandler.reset();
- PP.RemovePragmaHandler(FloatControlHandler.get());
- FloatControlHandler.reset();
- if (getLangOpts().MicrosoftExt) {
- PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
- MSDetectMismatchHandler.reset();
- PP.RemovePragmaHandler(MSPointersToMembers.get());
- MSPointersToMembers.reset();
- PP.RemovePragmaHandler(MSVtorDisp.get());
- MSVtorDisp.reset();
- PP.RemovePragmaHandler(MSInitSeg.get());
- MSInitSeg.reset();
- PP.RemovePragmaHandler(MSDataSeg.get());
- MSDataSeg.reset();
- PP.RemovePragmaHandler(MSBSSSeg.get());
- MSBSSSeg.reset();
- PP.RemovePragmaHandler(MSConstSeg.get());
- MSConstSeg.reset();
- PP.RemovePragmaHandler(MSCodeSeg.get());
- MSCodeSeg.reset();
- PP.RemovePragmaHandler(MSSection.get());
- MSSection.reset();
- PP.RemovePragmaHandler(MSStrictGuardStackCheck.get());
- MSStrictGuardStackCheck.reset();
- PP.RemovePragmaHandler(MSFunction.get());
- MSFunction.reset();
- PP.RemovePragmaHandler(MSAllocText.get());
- MSAllocText.reset();
- PP.RemovePragmaHandler(MSRuntimeChecks.get());
- MSRuntimeChecks.reset();
- PP.RemovePragmaHandler(MSIntrinsic.get());
- MSIntrinsic.reset();
- PP.RemovePragmaHandler(MSOptimize.get());
- MSOptimize.reset();
- PP.RemovePragmaHandler(MSFenvAccess.get());
- MSFenvAccess.reset();
- }
- if (getLangOpts().CUDA) {
- PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
- CUDAForceHostDeviceHandler.reset();
- }
- PP.RemovePragmaHandler("STDC", FPContractHandler.get());
- FPContractHandler.reset();
- PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get());
- STDCFenvAccessHandler.reset();
- PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get());
- STDCFenvRoundHandler.reset();
- PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
- STDCCXLIMITHandler.reset();
- PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
- STDCUnknownHandler.reset();
- PP.RemovePragmaHandler("clang", OptimizeHandler.get());
- OptimizeHandler.reset();
- PP.RemovePragmaHandler("clang", LoopHintHandler.get());
- LoopHintHandler.reset();
- PP.RemovePragmaHandler(UnrollHintHandler.get());
- PP.RemovePragmaHandler("GCC", UnrollHintHandler.get());
- UnrollHintHandler.reset();
- PP.RemovePragmaHandler(NoUnrollHintHandler.get());
- PP.RemovePragmaHandler("GCC", NoUnrollHintHandler.get());
- NoUnrollHintHandler.reset();
- PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
- UnrollAndJamHintHandler.reset();
- PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
- NoUnrollAndJamHintHandler.reset();
- PP.RemovePragmaHandler("clang", FPHandler.get());
- FPHandler.reset();
- PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
- AttributePragmaHandler.reset();
- PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
- MaxTokensHerePragmaHandler.reset();
- PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
- MaxTokensTotalPragmaHandler.reset();
- if (getTargetInfo().getTriple().isRISCV()) {
- PP.RemovePragmaHandler("clang", RISCVPragmaHandler.get());
- RISCVPragmaHandler.reset();
- }
- }
- /// Handle the annotation token produced for #pragma unused(...)
- ///
- /// Each annot_pragma_unused is followed by the argument token so e.g.
- /// "#pragma unused(x,y)" becomes:
- /// annot_pragma_unused 'x' annot_pragma_unused 'y'
- void Parser::HandlePragmaUnused() {
- assert(Tok.is(tok::annot_pragma_unused));
- SourceLocation UnusedLoc = ConsumeAnnotationToken();
- Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
- ConsumeToken(); // The argument token.
- }
- void Parser::HandlePragmaVisibility() {
- assert(Tok.is(tok::annot_pragma_vis));
- const IdentifierInfo *VisType =
- static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
- SourceLocation VisLoc = ConsumeAnnotationToken();
- Actions.ActOnPragmaVisibility(VisType, VisLoc);
- }
- namespace {
- struct PragmaPackInfo {
- Sema::PragmaMsStackAction Action;
- StringRef SlotLabel;
- Token Alignment;
- };
- } // end anonymous namespace
- void Parser::HandlePragmaPack() {
- assert(Tok.is(tok::annot_pragma_pack));
- PragmaPackInfo *Info =
- static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
- SourceLocation PragmaLoc = Tok.getLocation();
- ExprResult Alignment;
- if (Info->Alignment.is(tok::numeric_constant)) {
- Alignment = Actions.ActOnNumericConstant(Info->Alignment);
- if (Alignment.isInvalid()) {
- ConsumeAnnotationToken();
- return;
- }
- }
- Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
- Alignment.get());
- // Consume the token after processing the pragma to enable pragma-specific
- // #include warnings.
- ConsumeAnnotationToken();
- }
- void Parser::HandlePragmaMSStruct() {
- assert(Tok.is(tok::annot_pragma_msstruct));
- PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
- reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
- Actions.ActOnPragmaMSStruct(Kind);
- ConsumeAnnotationToken();
- }
- void Parser::HandlePragmaAlign() {
- assert(Tok.is(tok::annot_pragma_align));
- Sema::PragmaOptionsAlignKind Kind =
- static_cast<Sema::PragmaOptionsAlignKind>(
- reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
- Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
- // Consume the token after processing the pragma to enable pragma-specific
- // #include warnings.
- ConsumeAnnotationToken();
- }
- void Parser::HandlePragmaDump() {
- assert(Tok.is(tok::annot_pragma_dump));
- IdentifierInfo *II =
- reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
- Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
- ConsumeAnnotationToken();
- }
- void Parser::HandlePragmaWeak() {
- assert(Tok.is(tok::annot_pragma_weak));
- SourceLocation PragmaLoc = ConsumeAnnotationToken();
- Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
- Tok.getLocation());
- ConsumeToken(); // The weak name.
- }
- void Parser::HandlePragmaWeakAlias() {
- assert(Tok.is(tok::annot_pragma_weakalias));
- SourceLocation PragmaLoc = ConsumeAnnotationToken();
- IdentifierInfo *WeakName = Tok.getIdentifierInfo();
- SourceLocation WeakNameLoc = Tok.getLocation();
- ConsumeToken();
- IdentifierInfo *AliasName = Tok.getIdentifierInfo();
- SourceLocation AliasNameLoc = Tok.getLocation();
- ConsumeToken();
- Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
- WeakNameLoc, AliasNameLoc);
- }
- void Parser::HandlePragmaRedefineExtname() {
- assert(Tok.is(tok::annot_pragma_redefine_extname));
- SourceLocation RedefLoc = ConsumeAnnotationToken();
- IdentifierInfo *RedefName = Tok.getIdentifierInfo();
- SourceLocation RedefNameLoc = Tok.getLocation();
- ConsumeToken();
- IdentifierInfo *AliasName = Tok.getIdentifierInfo();
- SourceLocation AliasNameLoc = Tok.getLocation();
- ConsumeToken();
- Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
- RedefNameLoc, AliasNameLoc);
- }
- void Parser::HandlePragmaFPContract() {
- assert(Tok.is(tok::annot_pragma_fp_contract));
- tok::OnOffSwitch OOS =
- static_cast<tok::OnOffSwitch>(
- reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
- LangOptions::FPModeKind FPC;
- switch (OOS) {
- case tok::OOS_ON:
- FPC = LangOptions::FPM_On;
- break;
- case tok::OOS_OFF:
- FPC = LangOptions::FPM_Off;
- break;
- case tok::OOS_DEFAULT:
- FPC = getLangOpts().getDefaultFPContractMode();
- break;
- }
- SourceLocation PragmaLoc = ConsumeAnnotationToken();
- Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
- }
- void Parser::HandlePragmaFloatControl() {
- assert(Tok.is(tok::annot_pragma_float_control));
- // The value that is held on the PragmaFloatControlStack encodes
- // the PragmaFloatControl kind and the MSStackAction kind
- // into a single 32-bit word. The MsStackAction is the high 16 bits
- // and the FloatControl is the lower 16 bits. Use shift and bit-and
- // to decode the parts.
- uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
- Sema::PragmaMsStackAction Action =
- static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
- PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);
- SourceLocation PragmaLoc = ConsumeAnnotationToken();
- Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
- }
- void Parser::HandlePragmaFEnvAccess() {
- assert(Tok.is(tok::annot_pragma_fenv_access) ||
- Tok.is(tok::annot_pragma_fenv_access_ms));
- tok::OnOffSwitch OOS =
- static_cast<tok::OnOffSwitch>(
- reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
- bool IsEnabled;
- switch (OOS) {
- case tok::OOS_ON:
- IsEnabled = true;
- break;
- case tok::OOS_OFF:
- IsEnabled = false;
- break;
- case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
- IsEnabled = false;
- break;
- }
- SourceLocation PragmaLoc = ConsumeAnnotationToken();
- Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
- }
- void Parser::HandlePragmaFEnvRound() {
- assert(Tok.is(tok::annot_pragma_fenv_round));
- auto RM = static_cast<llvm::RoundingMode>(
- reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
- SourceLocation PragmaLoc = ConsumeAnnotationToken();
- Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);
- }
- StmtResult Parser::HandlePragmaCaptured()
- {
- assert(Tok.is(tok::annot_pragma_captured));
- ConsumeAnnotationToken();
- if (Tok.isNot(tok::l_brace)) {
- PP.Diag(Tok, diag::err_expected) << tok::l_brace;
- return StmtError();
- }
- SourceLocation Loc = Tok.getLocation();
- ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
- Scope::CompoundStmtScope);
- Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
- /*NumParams=*/1);
- StmtResult R = ParseCompoundStatement();
- CapturedRegionScope.Exit();
- if (R.isInvalid()) {
- Actions.ActOnCapturedRegionError();
- return StmtError();
- }
- return Actions.ActOnCapturedRegionEnd(R.get());
- }
- namespace {
- enum OpenCLExtState : char {
- Disable, Enable, Begin, End
- };
- typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
- }
- void Parser::HandlePragmaOpenCLExtension() {
- assert(Tok.is(tok::annot_pragma_opencl_extension));
- OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
- auto State = Data->second;
- auto Ident = Data->first;
- SourceLocation NameLoc = Tok.getLocation();
- ConsumeAnnotationToken();
- auto &Opt = Actions.getOpenCLOptions();
- auto Name = Ident->getName();
- // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
- // overriding all previously issued extension directives, but only if the
- // behavior is set to disable."
- if (Name == "all") {
- if (State == Disable)
- Opt.disableAll();
- else
- PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
- } else if (State == Begin) {
- if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
- Opt.support(Name);
- // FIXME: Default behavior of the extension pragma is not defined.
- // Therefore, it should never be added by default.
- Opt.acceptsPragma(Name);
- }
- } else if (State == End) {
- // There is no behavior for this directive. We only accept this for
- // backward compatibility.
- } else if (!Opt.isKnown(Name) || !Opt.isWithPragma(Name))
- PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
- else if (Opt.isSupportedExtension(Name, getLangOpts()))
- Opt.enable(Name, State == Enable);
- else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts()))
- PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
- else
- PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
- }
- void Parser::HandlePragmaMSPointersToMembers() {
- assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
- LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
- static_cast<LangOptions::PragmaMSPointersToMembersKind>(
- reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
- SourceLocation PragmaLoc = ConsumeAnnotationToken();
- Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
- }
- void Parser::HandlePragmaMSVtorDisp() {
- assert(Tok.is(tok::annot_pragma_ms_vtordisp));
- uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
- Sema::PragmaMsStackAction Action =
- static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
- MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
- SourceLocation PragmaLoc = ConsumeAnnotationToken();
- Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
- }
- void Parser::HandlePragmaMSPragma() {
- assert(Tok.is(tok::annot_pragma_ms_pragma));
- // Grab the tokens out of the annotation and enter them into the stream.
- auto TheTokens =
- (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
- PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
- /*IsReinject=*/true);
- SourceLocation PragmaLocation = ConsumeAnnotationToken();
- assert(Tok.isAnyIdentifier());
- StringRef PragmaName = Tok.getIdentifierInfo()->getName();
- PP.Lex(Tok); // pragma kind
- // Figure out which #pragma we're dealing with. The switch has no default
- // because lex shouldn't emit the annotation token for unrecognized pragmas.
- typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
- PragmaHandler Handler =
- llvm::StringSwitch<PragmaHandler>(PragmaName)
- .Case("data_seg", &Parser::HandlePragmaMSSegment)
- .Case("bss_seg", &Parser::HandlePragmaMSSegment)
- .Case("const_seg", &Parser::HandlePragmaMSSegment)
- .Case("code_seg", &Parser::HandlePragmaMSSegment)
- .Case("section", &Parser::HandlePragmaMSSection)
- .Case("init_seg", &Parser::HandlePragmaMSInitSeg)
- .Case("strict_gs_check", &Parser::HandlePragmaMSStrictGuardStackCheck)
- .Case("function", &Parser::HandlePragmaMSFunction)
- .Case("alloc_text", &Parser::HandlePragmaMSAllocText)
- .Case("optimize", &Parser::HandlePragmaMSOptimize);
- if (!(this->*Handler)(PragmaName, PragmaLocation)) {
- // Pragma handling failed, and has been diagnosed. Slurp up the tokens
- // until eof (really end of line) to prevent follow-on errors.
- while (Tok.isNot(tok::eof))
- PP.Lex(Tok);
- PP.Lex(Tok);
- }
- }
- bool Parser::HandlePragmaMSSection(StringRef PragmaName,
- SourceLocation PragmaLocation) {
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
- return false;
- }
- PP.Lex(Tok); // (
- // Parsing code for pragma section
- if (Tok.isNot(tok::string_literal)) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
- << PragmaName;
- return false;
- }
- ExprResult StringResult = ParseStringLiteralExpression();
- if (StringResult.isInvalid())
- return false; // Already diagnosed.
- StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
- if (SegmentName->getCharByteWidth() != 1) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
- << PragmaName;
- return false;
- }
- int SectionFlags = ASTContext::PSF_Read;
- bool SectionFlagsAreDefault = true;
- while (Tok.is(tok::comma)) {
- PP.Lex(Tok); // ,
- // Ignore "long" and "short".
- // They are undocumented, but widely used, section attributes which appear
- // to do nothing.
- if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
- PP.Lex(Tok); // long/short
- continue;
- }
- if (!Tok.isAnyIdentifier()) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
- << PragmaName;
- return false;
- }
- ASTContext::PragmaSectionFlag Flag =
- llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
- Tok.getIdentifierInfo()->getName())
- .Case("read", ASTContext::PSF_Read)
- .Case("write", ASTContext::PSF_Write)
- .Case("execute", ASTContext::PSF_Execute)
- .Case("shared", ASTContext::PSF_Invalid)
- .Case("nopage", ASTContext::PSF_Invalid)
- .Case("nocache", ASTContext::PSF_Invalid)
- .Case("discard", ASTContext::PSF_Invalid)
- .Case("remove", ASTContext::PSF_Invalid)
- .Default(ASTContext::PSF_None);
- if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
- PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
- ? diag::warn_pragma_invalid_specific_action
- : diag::warn_pragma_unsupported_action)
- << PragmaName << Tok.getIdentifierInfo()->getName();
- return false;
- }
- SectionFlags |= Flag;
- SectionFlagsAreDefault = false;
- PP.Lex(Tok); // Identifier
- }
- // If no section attributes are specified, the section will be marked as
- // read/write.
- if (SectionFlagsAreDefault)
- SectionFlags |= ASTContext::PSF_Write;
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
- return false;
- }
- PP.Lex(Tok); // )
- if (Tok.isNot(tok::eof)) {
- PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
- << PragmaName;
- return false;
- }
- PP.Lex(Tok); // eof
- Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
- return true;
- }
- bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
- SourceLocation PragmaLocation) {
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
- return false;
- }
- PP.Lex(Tok); // (
- Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
- StringRef SlotLabel;
- if (Tok.isAnyIdentifier()) {
- StringRef PushPop = Tok.getIdentifierInfo()->getName();
- if (PushPop == "push")
- Action = Sema::PSK_Push;
- else if (PushPop == "pop")
- Action = Sema::PSK_Pop;
- else {
- PP.Diag(PragmaLocation,
- diag::warn_pragma_expected_section_push_pop_or_name)
- << PragmaName;
- return false;
- }
- if (Action != Sema::PSK_Reset) {
- PP.Lex(Tok); // push | pop
- if (Tok.is(tok::comma)) {
- PP.Lex(Tok); // ,
- // If we've got a comma, we either need a label or a string.
- if (Tok.isAnyIdentifier()) {
- SlotLabel = Tok.getIdentifierInfo()->getName();
- PP.Lex(Tok); // identifier
- if (Tok.is(tok::comma))
- PP.Lex(Tok);
- else if (Tok.isNot(tok::r_paren)) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
- << PragmaName;
- return false;
- }
- }
- } else if (Tok.isNot(tok::r_paren)) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
- return false;
- }
- }
- }
- // Grab the string literal for our section name.
- StringLiteral *SegmentName = nullptr;
- if (Tok.isNot(tok::r_paren)) {
- if (Tok.isNot(tok::string_literal)) {
- unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
- diag::warn_pragma_expected_section_name :
- diag::warn_pragma_expected_section_label_or_name :
- diag::warn_pragma_expected_section_push_pop_or_name;
- PP.Diag(PragmaLocation, DiagID) << PragmaName;
- return false;
- }
- ExprResult StringResult = ParseStringLiteralExpression();
- if (StringResult.isInvalid())
- return false; // Already diagnosed.
- SegmentName = cast<StringLiteral>(StringResult.get());
- if (SegmentName->getCharByteWidth() != 1) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
- << PragmaName;
- return false;
- }
- // Setting section "" has no effect
- if (SegmentName->getLength())
- Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
- }
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
- return false;
- }
- PP.Lex(Tok); // )
- if (Tok.isNot(tok::eof)) {
- PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
- << PragmaName;
- return false;
- }
- PP.Lex(Tok); // eof
- Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
- SegmentName, PragmaName);
- return true;
- }
- // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
- bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
- SourceLocation PragmaLocation) {
- if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
- PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
- return false;
- }
- if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
- PragmaName))
- return false;
- // Parse either the known section names or the string section name.
- StringLiteral *SegmentName = nullptr;
- if (Tok.isAnyIdentifier()) {
- auto *II = Tok.getIdentifierInfo();
- StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
- .Case("compiler", "\".CRT$XCC\"")
- .Case("lib", "\".CRT$XCL\"")
- .Case("user", "\".CRT$XCU\"")
- .Default("");
- if (!Section.empty()) {
- // Pretend the user wrote the appropriate string literal here.
- Token Toks[1];
- Toks[0].startToken();
- Toks[0].setKind(tok::string_literal);
- Toks[0].setLocation(Tok.getLocation());
- Toks[0].setLiteralData(Section.data());
- Toks[0].setLength(Section.size());
- SegmentName =
- cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
- PP.Lex(Tok);
- }
- } else if (Tok.is(tok::string_literal)) {
- ExprResult StringResult = ParseStringLiteralExpression();
- if (StringResult.isInvalid())
- return false;
- SegmentName = cast<StringLiteral>(StringResult.get());
- if (SegmentName->getCharByteWidth() != 1) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
- << PragmaName;
- return false;
- }
- // FIXME: Add support for the '[, func-name]' part of the pragma.
- }
- if (!SegmentName) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
- return false;
- }
- if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
- PragmaName) ||
- ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
- PragmaName))
- return false;
- Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
- return true;
- }
- // #pragma strict_gs_check(pop)
- // #pragma strict_gs_check(push, "on" | "off")
- // #pragma strict_gs_check("on" | "off")
- bool Parser::HandlePragmaMSStrictGuardStackCheck(
- StringRef PragmaName, SourceLocation PragmaLocation) {
- if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
- PragmaName))
- return false;
- Sema::PragmaMsStackAction Action = Sema::PSK_Set;
- if (Tok.is(tok::identifier)) {
- StringRef PushPop = Tok.getIdentifierInfo()->getName();
- if (PushPop == "push") {
- PP.Lex(Tok);
- Action = Sema::PSK_Push;
- if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_punc,
- PragmaName))
- return false;
- } else if (PushPop == "pop") {
- PP.Lex(Tok);
- Action = Sema::PSK_Pop;
- }
- }
- bool Value = false;
- if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- if (II && II->isStr("off")) {
- PP.Lex(Tok);
- Value = false;
- } else if (II && II->isStr("on")) {
- PP.Lex(Tok);
- Value = true;
- } else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
- << PragmaName;
- return false;
- }
- }
- // Finish the pragma: ')' $
- if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
- PragmaName))
- return false;
- if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
- PragmaName))
- return false;
- Actions.ActOnPragmaMSStrictGuardStackCheck(PragmaLocation, Action, Value);
- return true;
- }
- bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
- SourceLocation PragmaLocation) {
- Token FirstTok = Tok;
- if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
- PragmaName))
- return false;
- StringRef Section;
- if (Tok.is(tok::string_literal)) {
- ExprResult StringResult = ParseStringLiteralExpression();
- if (StringResult.isInvalid())
- return false; // Already diagnosed.
- StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
- if (SegmentName->getCharByteWidth() != 1) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
- << PragmaName;
- return false;
- }
- Section = SegmentName->getString();
- } else if (Tok.is(tok::identifier)) {
- Section = Tok.getIdentifierInfo()->getName();
- PP.Lex(Tok);
- } else {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
- << PragmaName;
- return false;
- }
- if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
- PragmaName))
- return false;
- SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> Functions;
- while (true) {
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
- << PragmaName;
- return false;
- }
- IdentifierInfo *II = Tok.getIdentifierInfo();
- Functions.emplace_back(II, Tok.getLocation());
- PP.Lex(Tok);
- if (Tok.isNot(tok::comma))
- break;
- PP.Lex(Tok);
- }
- if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
- PragmaName) ||
- ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
- PragmaName))
- return false;
- Actions.ActOnPragmaMSAllocText(FirstTok.getLocation(), Section, Functions);
- return true;
- }
- static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
- StringRef Str = PragmaName.getIdentifierInfo()->getName();
- std::string ClangLoopStr("clang loop ");
- if (Str == "loop" && Option.getIdentifierInfo())
- ClangLoopStr += Option.getIdentifierInfo()->getName();
- return std::string(llvm::StringSwitch<StringRef>(Str)
- .Case("loop", ClangLoopStr)
- .Case("unroll_and_jam", Str)
- .Case("unroll", Str)
- .Default(""));
- }
- bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
- assert(Tok.is(tok::annot_pragma_loop_hint));
- PragmaLoopHintInfo *Info =
- static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
- IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
- Hint.PragmaNameLoc = IdentifierLoc::create(
- Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
- // It is possible that the loop hint has no option identifier, such as
- // #pragma unroll(4).
- IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
- ? Info->Option.getIdentifierInfo()
- : nullptr;
- Hint.OptionLoc = IdentifierLoc::create(
- Actions.Context, Info->Option.getLocation(), OptionInfo);
- llvm::ArrayRef<Token> Toks = Info->Toks;
- // Return a valid hint if pragma unroll or nounroll were specified
- // without an argument.
- auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
- .Cases("unroll", "nounroll", "unroll_and_jam",
- "nounroll_and_jam", true)
- .Default(false);
- if (Toks.empty() && IsLoopHint) {
- ConsumeAnnotationToken();
- Hint.Range = Info->PragmaName.getLocation();
- return true;
- }
- // The constant expression is always followed by an eof token, which increases
- // the TokSize by 1.
- assert(!Toks.empty() &&
- "PragmaLoopHintInfo::Toks must contain at least one token.");
- // If no option is specified the argument is assumed to be a constant expr.
- bool OptionUnroll = false;
- bool OptionUnrollAndJam = false;
- bool OptionDistribute = false;
- bool OptionPipelineDisabled = false;
- bool StateOption = false;
- if (OptionInfo) { // Pragma Unroll does not specify an option.
- OptionUnroll = OptionInfo->isStr("unroll");
- OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
- OptionDistribute = OptionInfo->isStr("distribute");
- OptionPipelineDisabled = OptionInfo->isStr("pipeline");
- StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
- .Case("vectorize", true)
- .Case("interleave", true)
- .Case("vectorize_predicate", true)
- .Default(false) ||
- OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
- OptionPipelineDisabled;
- }
- bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
- !OptionDistribute && !OptionPipelineDisabled;
- // Verify loop hint has an argument.
- if (Toks[0].is(tok::eof)) {
- ConsumeAnnotationToken();
- Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
- << /*StateArgument=*/StateOption
- << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
- << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
- return false;
- }
- // Validate the argument.
- if (StateOption) {
- ConsumeAnnotationToken();
- SourceLocation StateLoc = Toks[0].getLocation();
- IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
- bool Valid = StateInfo &&
- llvm::StringSwitch<bool>(StateInfo->getName())
- .Case("disable", true)
- .Case("enable", !OptionPipelineDisabled)
- .Case("full", OptionUnroll || OptionUnrollAndJam)
- .Case("assume_safety", AssumeSafetyArg)
- .Default(false);
- if (!Valid) {
- if (OptionPipelineDisabled) {
- Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
- } else {
- Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
- << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
- << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
- }
- return false;
- }
- if (Toks.size() > 2)
- Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << PragmaLoopHintString(Info->PragmaName, Info->Option);
- Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
- } else if (OptionInfo && OptionInfo->getName() == "vectorize_width") {
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
- /*IsReinject=*/false);
- ConsumeAnnotationToken();
- SourceLocation StateLoc = Toks[0].getLocation();
- IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
- StringRef IsScalableStr = StateInfo ? StateInfo->getName() : "";
- // Look for vectorize_width(fixed|scalable)
- if (IsScalableStr == "scalable" || IsScalableStr == "fixed") {
- PP.Lex(Tok); // Identifier
- if (Toks.size() > 2) {
- Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << PragmaLoopHintString(Info->PragmaName, Info->Option);
- while (Tok.isNot(tok::eof))
- ConsumeAnyToken();
- }
- Hint.StateLoc =
- IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
- ConsumeToken(); // Consume the constant expression eof terminator.
- } else {
- // Enter constant expression including eof terminator into token stream.
- ExprResult R = ParseConstantExpression();
- if (R.isInvalid() && !Tok.is(tok::comma))
- Diag(Toks[0].getLocation(),
- diag::note_pragma_loop_invalid_vectorize_option);
- bool Arg2Error = false;
- if (Tok.is(tok::comma)) {
- PP.Lex(Tok); // ,
- StateInfo = Tok.getIdentifierInfo();
- IsScalableStr = StateInfo->getName();
- if (IsScalableStr != "scalable" && IsScalableStr != "fixed") {
- Diag(Tok.getLocation(),
- diag::err_pragma_loop_invalid_vectorize_option);
- Arg2Error = true;
- } else
- Hint.StateLoc =
- IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
- PP.Lex(Tok); // Identifier
- }
- // Tokens following an error in an ill-formed constant expression will
- // remain in the token stream and must be removed.
- if (Tok.isNot(tok::eof)) {
- Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << PragmaLoopHintString(Info->PragmaName, Info->Option);
- while (Tok.isNot(tok::eof))
- ConsumeAnyToken();
- }
- ConsumeToken(); // Consume the constant expression eof terminator.
- if (Arg2Error || R.isInvalid() ||
- Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
- return false;
- // Argument is a constant expression with an integer type.
- Hint.ValueExpr = R.get();
- }
- } else {
- // Enter constant expression including eof terminator into token stream.
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
- /*IsReinject=*/false);
- ConsumeAnnotationToken();
- ExprResult R = ParseConstantExpression();
- // Tokens following an error in an ill-formed constant expression will
- // remain in the token stream and must be removed.
- if (Tok.isNot(tok::eof)) {
- Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << PragmaLoopHintString(Info->PragmaName, Info->Option);
- while (Tok.isNot(tok::eof))
- ConsumeAnyToken();
- }
- ConsumeToken(); // Consume the constant expression eof terminator.
- if (R.isInvalid() ||
- Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
- return false;
- // Argument is a constant expression with an integer type.
- Hint.ValueExpr = R.get();
- }
- Hint.Range = SourceRange(Info->PragmaName.getLocation(),
- Info->Toks.back().getLocation());
- return true;
- }
- namespace {
- struct PragmaAttributeInfo {
- enum ActionType { Push, Pop, Attribute };
- ParsedAttributes &Attributes;
- ActionType Action;
- const IdentifierInfo *Namespace = nullptr;
- ArrayRef<Token> Tokens;
- PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
- };
- #include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
- } // end anonymous namespace
- static StringRef getIdentifier(const Token &Tok) {
- if (Tok.is(tok::identifier))
- return Tok.getIdentifierInfo()->getName();
- const char *S = tok::getKeywordSpelling(Tok.getKind());
- if (!S)
- return "";
- return S;
- }
- static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
- using namespace attr;
- switch (Rule) {
- #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
- case Value: \
- return IsAbstract;
- #include "clang/Basic/AttrSubMatchRulesList.inc"
- }
- llvm_unreachable("Invalid attribute subject match rule");
- return false;
- }
- static void diagnoseExpectedAttributeSubjectSubRule(
- Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
- SourceLocation SubRuleLoc) {
- auto Diagnostic =
- PRef.Diag(SubRuleLoc,
- diag::err_pragma_attribute_expected_subject_sub_identifier)
- << PrimaryRuleName;
- if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
- Diagnostic << /*SubRulesSupported=*/1 << SubRules;
- else
- Diagnostic << /*SubRulesSupported=*/0;
- }
- static void diagnoseUnknownAttributeSubjectSubRule(
- Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
- StringRef SubRuleName, SourceLocation SubRuleLoc) {
- auto Diagnostic =
- PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
- << SubRuleName << PrimaryRuleName;
- if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
- Diagnostic << /*SubRulesSupported=*/1 << SubRules;
- else
- Diagnostic << /*SubRulesSupported=*/0;
- }
- bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
- attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
- SourceLocation &LastMatchRuleEndLoc) {
- bool IsAny = false;
- BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
- if (getIdentifier(Tok) == "any") {
- AnyLoc = ConsumeToken();
- IsAny = true;
- if (AnyParens.expectAndConsume())
- return true;
- }
- do {
- // Parse the subject matcher rule.
- StringRef Name = getIdentifier(Tok);
- if (Name.empty()) {
- Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
- return true;
- }
- std::pair<std::optional<attr::SubjectMatchRule>,
- std::optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
- Rule = isAttributeSubjectMatchRule(Name);
- if (!Rule.first) {
- Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
- return true;
- }
- attr::SubjectMatchRule PrimaryRule = *Rule.first;
- SourceLocation RuleLoc = ConsumeToken();
- BalancedDelimiterTracker Parens(*this, tok::l_paren);
- if (isAbstractAttrMatcherRule(PrimaryRule)) {
- if (Parens.expectAndConsume())
- return true;
- } else if (Parens.consumeOpen()) {
- if (!SubjectMatchRules
- .insert(
- std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
- .second)
- Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
- << Name
- << FixItHint::CreateRemoval(SourceRange(
- RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
- LastMatchRuleEndLoc = RuleLoc;
- continue;
- }
- // Parse the sub-rules.
- StringRef SubRuleName = getIdentifier(Tok);
- if (SubRuleName.empty()) {
- diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
- Tok.getLocation());
- return true;
- }
- attr::SubjectMatchRule SubRule;
- if (SubRuleName == "unless") {
- SourceLocation SubRuleLoc = ConsumeToken();
- BalancedDelimiterTracker Parens(*this, tok::l_paren);
- if (Parens.expectAndConsume())
- return true;
- SubRuleName = getIdentifier(Tok);
- if (SubRuleName.empty()) {
- diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
- SubRuleLoc);
- return true;
- }
- auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
- if (!SubRuleOrNone) {
- std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
- diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
- SubRuleUnlessName, SubRuleLoc);
- return true;
- }
- SubRule = *SubRuleOrNone;
- ConsumeToken();
- if (Parens.consumeClose())
- return true;
- } else {
- auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
- if (!SubRuleOrNone) {
- diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
- SubRuleName, Tok.getLocation());
- return true;
- }
- SubRule = *SubRuleOrNone;
- ConsumeToken();
- }
- SourceLocation RuleEndLoc = Tok.getLocation();
- LastMatchRuleEndLoc = RuleEndLoc;
- if (Parens.consumeClose())
- return true;
- if (!SubjectMatchRules
- .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
- .second) {
- Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
- << attr::getSubjectMatchRuleSpelling(SubRule)
- << FixItHint::CreateRemoval(SourceRange(
- RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
- continue;
- }
- } while (IsAny && TryConsumeToken(tok::comma));
- if (IsAny)
- if (AnyParens.consumeClose())
- return true;
- return false;
- }
- namespace {
- /// Describes the stage at which attribute subject rule parsing was interrupted.
- enum class MissingAttributeSubjectRulesRecoveryPoint {
- Comma,
- ApplyTo,
- Equals,
- Any,
- None,
- };
- MissingAttributeSubjectRulesRecoveryPoint
- getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
- if (const auto *II = Tok.getIdentifierInfo()) {
- if (II->isStr("apply_to"))
- return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
- if (II->isStr("any"))
- return MissingAttributeSubjectRulesRecoveryPoint::Any;
- }
- if (Tok.is(tok::equal))
- return MissingAttributeSubjectRulesRecoveryPoint::Equals;
- return MissingAttributeSubjectRulesRecoveryPoint::None;
- }
- /// Creates a diagnostic for the attribute subject rule parsing diagnostic that
- /// suggests the possible attribute subject rules in a fix-it together with
- /// any other missing tokens.
- DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
- unsigned DiagID, ParsedAttributes &Attrs,
- MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
- SourceLocation Loc = PRef.getEndOfPreviousToken();
- if (Loc.isInvalid())
- Loc = PRef.getCurToken().getLocation();
- auto Diagnostic = PRef.Diag(Loc, DiagID);
- std::string FixIt;
- MissingAttributeSubjectRulesRecoveryPoint EndPoint =
- getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
- if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
- FixIt = ", ";
- if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
- EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
- FixIt += "apply_to";
- if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
- EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
- FixIt += " = ";
- SourceRange FixItRange(Loc);
- if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
- // Gather the subject match rules that are supported by the attribute.
- // Add all the possible rules initially.
- llvm::BitVector IsMatchRuleAvailable(attr::SubjectMatchRule_Last + 1, true);
- // Remove the ones that are not supported by any of the attributes.
- for (const ParsedAttr &Attribute : Attrs) {
- SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> MatchRules;
- Attribute.getMatchRules(PRef.getLangOpts(), MatchRules);
- llvm::BitVector IsSupported(attr::SubjectMatchRule_Last + 1);
- for (const auto &Rule : MatchRules) {
- // Ensure that the missing rule is reported in the fix-it only when it's
- // supported in the current language mode.
- if (!Rule.second)
- continue;
- IsSupported[Rule.first] = true;
- }
- IsMatchRuleAvailable &= IsSupported;
- }
- if (IsMatchRuleAvailable.count() == 0) {
- // FIXME: We can emit a "fix-it" with a subject list placeholder when
- // placeholders will be supported by the fix-its.
- return Diagnostic;
- }
- FixIt += "any(";
- bool NeedsComma = false;
- for (unsigned I = 0; I <= attr::SubjectMatchRule_Last; I++) {
- if (!IsMatchRuleAvailable[I])
- continue;
- if (NeedsComma)
- FixIt += ", ";
- else
- NeedsComma = true;
- FixIt += attr::getSubjectMatchRuleSpelling(
- static_cast<attr::SubjectMatchRule>(I));
- }
- FixIt += ")";
- // Check if we need to remove the range
- PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
- FixItRange.setEnd(PRef.getCurToken().getLocation());
- }
- if (FixItRange.getBegin() == FixItRange.getEnd())
- Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
- else
- Diagnostic << FixItHint::CreateReplacement(
- CharSourceRange::getCharRange(FixItRange), FixIt);
- return Diagnostic;
- }
- } // end anonymous namespace
- void Parser::HandlePragmaAttribute() {
- assert(Tok.is(tok::annot_pragma_attribute) &&
- "Expected #pragma attribute annotation token");
- SourceLocation PragmaLoc = Tok.getLocation();
- auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
- if (Info->Action == PragmaAttributeInfo::Pop) {
- ConsumeAnnotationToken();
- Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
- return;
- }
- // Parse the actual attribute with its arguments.
- assert((Info->Action == PragmaAttributeInfo::Push ||
- Info->Action == PragmaAttributeInfo::Attribute) &&
- "Unexpected #pragma attribute command");
- if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
- ConsumeAnnotationToken();
- Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
- return;
- }
- PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
- /*IsReinject=*/false);
- ConsumeAnnotationToken();
- ParsedAttributes &Attrs = Info->Attributes;
- Attrs.clearListOnly();
- auto SkipToEnd = [this]() {
- SkipUntil(tok::eof, StopBeforeMatch);
- ConsumeToken();
- };
- if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
- // Parse the CXX11 style attribute.
- ParseCXX11AttributeSpecifier(Attrs);
- } else if (Tok.is(tok::kw___attribute)) {
- ConsumeToken();
- if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
- "attribute"))
- return SkipToEnd();
- if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
- return SkipToEnd();
- // FIXME: The practical usefulness of completion here is limited because
- // we only get here if the line has balanced parens.
- if (Tok.is(tok::code_completion)) {
- cutOffParsing();
- // FIXME: suppress completion of unsupported attributes?
- Actions.CodeCompleteAttribute(AttributeCommonInfo::Syntax::AS_GNU);
- return SkipToEnd();
- }
- // Parse the comma-separated list of attributes.
- do {
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
- SkipToEnd();
- return;
- }
- IdentifierInfo *AttrName = Tok.getIdentifierInfo();
- SourceLocation AttrNameLoc = ConsumeToken();
- if (Tok.isNot(tok::l_paren))
- Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
- ParsedAttr::AS_GNU);
- else
- ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
- /*ScopeName=*/nullptr,
- /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
- /*Declarator=*/nullptr);
- } while (TryConsumeToken(tok::comma));
- if (ExpectAndConsume(tok::r_paren))
- return SkipToEnd();
- if (ExpectAndConsume(tok::r_paren))
- return SkipToEnd();
- } else if (Tok.is(tok::kw___declspec)) {
- ParseMicrosoftDeclSpecs(Attrs);
- } else {
- Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
- if (Tok.getIdentifierInfo()) {
- // If we suspect that this is an attribute suggest the use of
- // '__attribute__'.
- if (ParsedAttr::getParsedKind(
- Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
- ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
- SourceLocation InsertStartLoc = Tok.getLocation();
- ConsumeToken();
- if (Tok.is(tok::l_paren)) {
- ConsumeAnyToken();
- SkipUntil(tok::r_paren, StopBeforeMatch);
- if (Tok.isNot(tok::r_paren))
- return SkipToEnd();
- }
- Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
- << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
- << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
- }
- }
- SkipToEnd();
- return;
- }
- if (Attrs.empty() || Attrs.begin()->isInvalid()) {
- SkipToEnd();
- return;
- }
- for (const ParsedAttr &Attribute : Attrs) {
- if (!Attribute.isSupportedByPragmaAttribute()) {
- Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
- << Attribute;
- SkipToEnd();
- return;
- }
- }
- // Parse the subject-list.
- if (!TryConsumeToken(tok::comma)) {
- createExpectedAttributeSubjectRulesTokenDiagnostic(
- diag::err_expected, Attrs,
- MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
- << tok::comma;
- SkipToEnd();
- return;
- }
- if (Tok.isNot(tok::identifier)) {
- createExpectedAttributeSubjectRulesTokenDiagnostic(
- diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
- MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
- SkipToEnd();
- return;
- }
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- if (!II->isStr("apply_to")) {
- createExpectedAttributeSubjectRulesTokenDiagnostic(
- diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
- MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
- SkipToEnd();
- return;
- }
- ConsumeToken();
- if (!TryConsumeToken(tok::equal)) {
- createExpectedAttributeSubjectRulesTokenDiagnostic(
- diag::err_expected, Attrs,
- MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
- << tok::equal;
- SkipToEnd();
- return;
- }
- attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
- SourceLocation AnyLoc, LastMatchRuleEndLoc;
- if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
- LastMatchRuleEndLoc)) {
- SkipToEnd();
- return;
- }
- // Tokens following an ill-formed attribute will remain in the token stream
- // and must be removed.
- if (Tok.isNot(tok::eof)) {
- Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
- SkipToEnd();
- return;
- }
- // Consume the eof terminator token.
- ConsumeToken();
- // Handle a mixed push/attribute by desurging to a push, then an attribute.
- if (Info->Action == PragmaAttributeInfo::Push)
- Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
- for (ParsedAttr &Attribute : Attrs) {
- Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
- SubjectMatchRules);
- }
- }
- // #pragma GCC visibility comes in two variants:
- // 'push' '(' [visibility] ')'
- // 'pop'
- void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &VisTok) {
- SourceLocation VisLoc = VisTok.getLocation();
- Token Tok;
- PP.LexUnexpandedToken(Tok);
- const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
- const IdentifierInfo *VisType;
- if (PushPop && PushPop->isStr("pop")) {
- VisType = nullptr;
- } else if (PushPop && PushPop->isStr("push")) {
- PP.LexUnexpandedToken(Tok);
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
- << "visibility";
- return;
- }
- PP.LexUnexpandedToken(Tok);
- VisType = Tok.getIdentifierInfo();
- if (!VisType) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
- << "visibility";
- return;
- }
- PP.LexUnexpandedToken(Tok);
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
- << "visibility";
- return;
- }
- } else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
- << "visibility";
- return;
- }
- SourceLocation EndLoc = Tok.getLocation();
- PP.LexUnexpandedToken(Tok);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "visibility";
- return;
- }
- auto Toks = std::make_unique<Token[]>(1);
- Toks[0].startToken();
- Toks[0].setKind(tok::annot_pragma_vis);
- Toks[0].setLocation(VisLoc);
- Toks[0].setAnnotationEndLoc(EndLoc);
- Toks[0].setAnnotationValue(
- const_cast<void *>(static_cast<const void *>(VisType)));
- PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- }
- // #pragma pack(...) comes in the following delicious flavors:
- // pack '(' [integer] ')'
- // pack '(' 'show' ')'
- // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
- void PragmaPackHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &PackTok) {
- SourceLocation PackLoc = PackTok.getLocation();
- Token Tok;
- PP.Lex(Tok);
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
- return;
- }
- Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
- StringRef SlotLabel;
- Token Alignment;
- Alignment.startToken();
- PP.Lex(Tok);
- if (Tok.is(tok::numeric_constant)) {
- Alignment = Tok;
- PP.Lex(Tok);
- // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
- // the push/pop stack.
- // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)
- Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack)
- ? Sema::PSK_Push_Set
- : Sema::PSK_Set;
- } else if (Tok.is(tok::identifier)) {
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- if (II->isStr("show")) {
- Action = Sema::PSK_Show;
- PP.Lex(Tok);
- } else {
- if (II->isStr("push")) {
- Action = Sema::PSK_Push;
- } else if (II->isStr("pop")) {
- Action = Sema::PSK_Pop;
- } else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
- return;
- }
- PP.Lex(Tok);
- if (Tok.is(tok::comma)) {
- PP.Lex(Tok);
- if (Tok.is(tok::numeric_constant)) {
- Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
- Alignment = Tok;
- PP.Lex(Tok);
- } else if (Tok.is(tok::identifier)) {
- SlotLabel = Tok.getIdentifierInfo()->getName();
- PP.Lex(Tok);
- if (Tok.is(tok::comma)) {
- PP.Lex(Tok);
- if (Tok.isNot(tok::numeric_constant)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
- return;
- }
- Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
- Alignment = Tok;
- PP.Lex(Tok);
- }
- } else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
- return;
- }
- }
- }
- } else if (PP.getLangOpts().ApplePragmaPack ||
- PP.getLangOpts().XLPragmaPack) {
- // In MSVC/gcc, #pragma pack() resets the alignment without affecting
- // the push/pop stack.
- // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma
- // pack(pop).
- Action = Sema::PSK_Pop;
- }
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
- return;
- }
- SourceLocation RParenLoc = Tok.getLocation();
- PP.Lex(Tok);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
- return;
- }
- PragmaPackInfo *Info =
- PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
- Info->Action = Action;
- Info->SlotLabel = SlotLabel;
- Info->Alignment = Alignment;
- MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
- 1);
- Toks[0].startToken();
- Toks[0].setKind(tok::annot_pragma_pack);
- Toks[0].setLocation(PackLoc);
- Toks[0].setAnnotationEndLoc(RParenLoc);
- Toks[0].setAnnotationValue(static_cast<void*>(Info));
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- }
- // #pragma ms_struct on
- // #pragma ms_struct off
- void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &MSStructTok) {
- PragmaMSStructKind Kind = PMSST_OFF;
- Token Tok;
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
- return;
- }
- SourceLocation EndLoc = Tok.getLocation();
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- if (II->isStr("on")) {
- Kind = PMSST_ON;
- PP.Lex(Tok);
- }
- else if (II->isStr("off") || II->isStr("reset"))
- PP.Lex(Tok);
- else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
- return;
- }
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "ms_struct";
- return;
- }
- MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
- 1);
- Toks[0].startToken();
- Toks[0].setKind(tok::annot_pragma_msstruct);
- Toks[0].setLocation(MSStructTok.getLocation());
- Toks[0].setAnnotationEndLoc(EndLoc);
- Toks[0].setAnnotationValue(reinterpret_cast<void*>(
- static_cast<uintptr_t>(Kind)));
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- }
- // #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
- void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &FirstToken) {
- Token Tok;
- auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
- PP.Lex(Tok); // eat 'section'
- while (Tok.isNot(tok::eod)) {
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
- return;
- }
- const IdentifierInfo *SecType = Tok.getIdentifierInfo();
- if (SecType->isStr("bss"))
- SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
- else if (SecType->isStr("data"))
- SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
- else if (SecType->isStr("rodata"))
- SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
- else if (SecType->isStr("relro"))
- SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;
- else if (SecType->isStr("text"))
- SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
- else {
- PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
- return;
- }
- SourceLocation PragmaLocation = Tok.getLocation();
- PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
- if (Tok.isNot(tok::equal)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
- return;
- }
- std::string SecName;
- if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
- return;
- Actions.ActOnPragmaClangSection(
- PragmaLocation,
- (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set
- : Sema::PragmaClangSectionAction::PCSA_Clear),
- SecKind, SecName);
- }
- }
- // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
- // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
- // #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
- static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
- bool IsOptions) {
- Token Tok;
- if (IsOptions) {
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier) ||
- !Tok.getIdentifierInfo()->isStr("align")) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
- return;
- }
- }
- PP.Lex(Tok);
- if (PP.getLangOpts().XLPragmaPack) {
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";
- return;
- }
- } else if (Tok.isNot(tok::equal)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
- << IsOptions;
- return;
- }
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
- << (IsOptions ? "options" : "align");
- return;
- }
- Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- if (II->isStr("native"))
- Kind = Sema::POAK_Native;
- else if (II->isStr("natural"))
- Kind = Sema::POAK_Natural;
- else if (II->isStr("packed"))
- Kind = Sema::POAK_Packed;
- else if (II->isStr("power"))
- Kind = Sema::POAK_Power;
- else if (II->isStr("mac68k"))
- Kind = Sema::POAK_Mac68k;
- else if (II->isStr("reset"))
- Kind = Sema::POAK_Reset;
- else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
- << IsOptions;
- return;
- }
- if (PP.getLangOpts().XLPragmaPack) {
- PP.Lex(Tok);
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";
- return;
- }
- }
- SourceLocation EndLoc = Tok.getLocation();
- PP.Lex(Tok);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << (IsOptions ? "options" : "align");
- return;
- }
- MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
- 1);
- Toks[0].startToken();
- Toks[0].setKind(tok::annot_pragma_align);
- Toks[0].setLocation(FirstTok.getLocation());
- Toks[0].setAnnotationEndLoc(EndLoc);
- Toks[0].setAnnotationValue(reinterpret_cast<void*>(
- static_cast<uintptr_t>(Kind)));
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- }
- void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &AlignTok) {
- ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
- }
- void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &OptionsTok) {
- ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
- }
- // #pragma unused(identifier)
- void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &UnusedTok) {
- // FIXME: Should we be expanding macros here? My guess is no.
- SourceLocation UnusedLoc = UnusedTok.getLocation();
- // Lex the left '('.
- Token Tok;
- PP.Lex(Tok);
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
- return;
- }
- // Lex the declaration reference(s).
- SmallVector<Token, 5> Identifiers;
- SourceLocation RParenLoc;
- bool LexID = true;
- while (true) {
- PP.Lex(Tok);
- if (LexID) {
- if (Tok.is(tok::identifier)) {
- Identifiers.push_back(Tok);
- LexID = false;
- continue;
- }
- // Illegal token!
- PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
- return;
- }
- // We are execting a ')' or a ','.
- if (Tok.is(tok::comma)) {
- LexID = true;
- continue;
- }
- if (Tok.is(tok::r_paren)) {
- RParenLoc = Tok.getLocation();
- break;
- }
- // Illegal token!
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
- return;
- }
- PP.Lex(Tok);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
- "unused";
- return;
- }
- // Verify that we have a location for the right parenthesis.
- assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
- assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
- // For each identifier token, insert into the token stream a
- // annot_pragma_unused token followed by the identifier token.
- // This allows us to cache a "#pragma unused" that occurs inside an inline
- // C++ member function.
- MutableArrayRef<Token> Toks(
- PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
- 2 * Identifiers.size());
- for (unsigned i=0; i != Identifiers.size(); i++) {
- Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
- pragmaUnusedTok.startToken();
- pragmaUnusedTok.setKind(tok::annot_pragma_unused);
- pragmaUnusedTok.setLocation(UnusedLoc);
- idTok = Identifiers[i];
- }
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- }
- // #pragma weak identifier
- // #pragma weak identifier '=' identifier
- void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &WeakTok) {
- SourceLocation WeakLoc = WeakTok.getLocation();
- Token Tok;
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
- return;
- }
- Token WeakName = Tok;
- bool HasAlias = false;
- Token AliasName;
- PP.Lex(Tok);
- if (Tok.is(tok::equal)) {
- HasAlias = true;
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
- << "weak";
- return;
- }
- AliasName = Tok;
- PP.Lex(Tok);
- }
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
- return;
- }
- if (HasAlias) {
- MutableArrayRef<Token> Toks(
- PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
- Token &pragmaUnusedTok = Toks[0];
- pragmaUnusedTok.startToken();
- pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
- pragmaUnusedTok.setLocation(WeakLoc);
- pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
- Toks[1] = WeakName;
- Toks[2] = AliasName;
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- } else {
- MutableArrayRef<Token> Toks(
- PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
- Token &pragmaUnusedTok = Toks[0];
- pragmaUnusedTok.startToken();
- pragmaUnusedTok.setKind(tok::annot_pragma_weak);
- pragmaUnusedTok.setLocation(WeakLoc);
- pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
- Toks[1] = WeakName;
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- }
- }
- // #pragma redefine_extname identifier identifier
- void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &RedefToken) {
- SourceLocation RedefLoc = RedefToken.getLocation();
- Token Tok;
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
- "redefine_extname";
- return;
- }
- Token RedefName = Tok;
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
- << "redefine_extname";
- return;
- }
- Token AliasName = Tok;
- PP.Lex(Tok);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
- "redefine_extname";
- return;
- }
- MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
- 3);
- Token &pragmaRedefTok = Toks[0];
- pragmaRedefTok.startToken();
- pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
- pragmaRedefTok.setLocation(RedefLoc);
- pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
- Toks[1] = RedefName;
- Toks[2] = AliasName;
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- }
- void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- tok::OnOffSwitch OOS;
- if (PP.LexOnOffSwitch(OOS))
- return;
- MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
- 1);
- Toks[0].startToken();
- Toks[0].setKind(tok::annot_pragma_fp_contract);
- Toks[0].setLocation(Tok.getLocation());
- Toks[0].setAnnotationEndLoc(Tok.getLocation());
- Toks[0].setAnnotationValue(reinterpret_cast<void*>(
- static_cast<uintptr_t>(OOS)));
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- }
- void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- PP.LexUnexpandedToken(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
- "OPENCL";
- return;
- }
- IdentifierInfo *Ext = Tok.getIdentifierInfo();
- SourceLocation NameLoc = Tok.getLocation();
- PP.Lex(Tok);
- if (Tok.isNot(tok::colon)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
- return;
- }
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
- return;
- }
- IdentifierInfo *Pred = Tok.getIdentifierInfo();
- OpenCLExtState State;
- if (Pred->isStr("enable")) {
- State = Enable;
- } else if (Pred->isStr("disable")) {
- State = Disable;
- } else if (Pred->isStr("begin"))
- State = Begin;
- else if (Pred->isStr("end"))
- State = End;
- else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
- << Ext->isStr("all");
- return;
- }
- SourceLocation StateLoc = Tok.getLocation();
- PP.Lex(Tok);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
- "OPENCL EXTENSION";
- return;
- }
- auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
- Info->first = Ext;
- Info->second = State;
- MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
- 1);
- Toks[0].startToken();
- Toks[0].setKind(tok::annot_pragma_opencl_extension);
- Toks[0].setLocation(NameLoc);
- Toks[0].setAnnotationValue(static_cast<void*>(Info));
- Toks[0].setAnnotationEndLoc(StateLoc);
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- if (PP.getPPCallbacks())
- PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
- StateLoc, State);
- }
- /// Handle '#pragma omp ...' when OpenMP is disabled.
- ///
- void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &FirstTok) {
- if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
- FirstTok.getLocation())) {
- PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
- PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
- diag::Severity::Ignored, SourceLocation());
- }
- PP.DiscardUntilEndOfDirective();
- }
- /// Handle '#pragma omp ...' when OpenMP is enabled.
- ///
- void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &FirstTok) {
- SmallVector<Token, 16> Pragma;
- Token Tok;
- Tok.startToken();
- Tok.setKind(tok::annot_pragma_openmp);
- Tok.setLocation(Introducer.Loc);
- while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
- Pragma.push_back(Tok);
- PP.Lex(Tok);
- if (Tok.is(tok::annot_pragma_openmp)) {
- PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
- unsigned InnerPragmaCnt = 1;
- while (InnerPragmaCnt != 0) {
- PP.Lex(Tok);
- if (Tok.is(tok::annot_pragma_openmp))
- ++InnerPragmaCnt;
- else if (Tok.is(tok::annot_pragma_openmp_end))
- --InnerPragmaCnt;
- }
- PP.Lex(Tok);
- }
- }
- SourceLocation EodLoc = Tok.getLocation();
- Tok.startToken();
- Tok.setKind(tok::annot_pragma_openmp_end);
- Tok.setLocation(EodLoc);
- Pragma.push_back(Tok);
- auto Toks = std::make_unique<Token[]>(Pragma.size());
- std::copy(Pragma.begin(), Pragma.end(), Toks.get());
- PP.EnterTokenStream(std::move(Toks), Pragma.size(),
- /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
- }
- /// Handle '#pragma pointers_to_members'
- // The grammar for this pragma is as follows:
- //
- // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
- //
- // #pragma pointers_to_members '(' 'best_case' ')'
- // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
- // #pragma pointers_to_members '(' inheritance-model ')'
- void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- SourceLocation PointersToMembersLoc = Tok.getLocation();
- PP.Lex(Tok);
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
- << "pointers_to_members";
- return;
- }
- PP.Lex(Tok);
- const IdentifierInfo *Arg = Tok.getIdentifierInfo();
- if (!Arg) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
- << "pointers_to_members";
- return;
- }
- PP.Lex(Tok);
- LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
- if (Arg->isStr("best_case")) {
- RepresentationMethod = LangOptions::PPTMK_BestCase;
- } else {
- if (Arg->isStr("full_generality")) {
- if (Tok.is(tok::comma)) {
- PP.Lex(Tok);
- Arg = Tok.getIdentifierInfo();
- if (!Arg) {
- PP.Diag(Tok.getLocation(),
- diag::err_pragma_pointers_to_members_unknown_kind)
- << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
- return;
- }
- PP.Lex(Tok);
- } else if (Tok.is(tok::r_paren)) {
- // #pragma pointers_to_members(full_generality) implicitly specifies
- // virtual_inheritance.
- Arg = nullptr;
- RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
- } else {
- PP.Diag(Tok.getLocation(), diag::err_expected_punc)
- << "full_generality";
- return;
- }
- }
- if (Arg) {
- if (Arg->isStr("single_inheritance")) {
- RepresentationMethod =
- LangOptions::PPTMK_FullGeneralitySingleInheritance;
- } else if (Arg->isStr("multiple_inheritance")) {
- RepresentationMethod =
- LangOptions::PPTMK_FullGeneralityMultipleInheritance;
- } else if (Arg->isStr("virtual_inheritance")) {
- RepresentationMethod =
- LangOptions::PPTMK_FullGeneralityVirtualInheritance;
- } else {
- PP.Diag(Tok.getLocation(),
- diag::err_pragma_pointers_to_members_unknown_kind)
- << Arg << /*HasPointerDeclaration*/ 1;
- return;
- }
- }
- }
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
- << (Arg ? Arg->getName() : "full_generality");
- return;
- }
- SourceLocation EndLoc = Tok.getLocation();
- PP.Lex(Tok);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "pointers_to_members";
- return;
- }
- Token AnnotTok;
- AnnotTok.startToken();
- AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
- AnnotTok.setLocation(PointersToMembersLoc);
- AnnotTok.setAnnotationEndLoc(EndLoc);
- AnnotTok.setAnnotationValue(
- reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
- PP.EnterToken(AnnotTok, /*IsReinject=*/true);
- }
- /// Handle '#pragma vtordisp'
- // The grammar for this pragma is as follows:
- //
- // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
- //
- // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
- // #pragma vtordisp '(' 'pop' ')'
- // #pragma vtordisp '(' ')'
- void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer, Token &Tok) {
- SourceLocation VtorDispLoc = Tok.getLocation();
- PP.Lex(Tok);
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
- return;
- }
- PP.Lex(Tok);
- Sema::PragmaMsStackAction Action = Sema::PSK_Set;
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- if (II) {
- if (II->isStr("push")) {
- // #pragma vtordisp(push, mode)
- PP.Lex(Tok);
- if (Tok.isNot(tok::comma)) {
- PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
- return;
- }
- PP.Lex(Tok);
- Action = Sema::PSK_Push_Set;
- // not push, could be on/off
- } else if (II->isStr("pop")) {
- // #pragma vtordisp(pop)
- PP.Lex(Tok);
- Action = Sema::PSK_Pop;
- }
- // not push or pop, could be on/off
- } else {
- if (Tok.is(tok::r_paren)) {
- // #pragma vtordisp()
- Action = Sema::PSK_Reset;
- }
- }
- uint64_t Value = 0;
- if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- if (II && II->isStr("off")) {
- PP.Lex(Tok);
- Value = 0;
- } else if (II && II->isStr("on")) {
- PP.Lex(Tok);
- Value = 1;
- } else if (Tok.is(tok::numeric_constant) &&
- PP.parseSimpleIntegerLiteral(Tok, Value)) {
- if (Value > 2) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
- << 0 << 2 << "vtordisp";
- return;
- }
- } else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
- << "vtordisp";
- return;
- }
- }
- // Finish the pragma: ')' $
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
- return;
- }
- SourceLocation EndLoc = Tok.getLocation();
- PP.Lex(Tok);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "vtordisp";
- return;
- }
- // Enter the annotation.
- Token AnnotTok;
- AnnotTok.startToken();
- AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
- AnnotTok.setLocation(VtorDispLoc);
- AnnotTok.setAnnotationEndLoc(EndLoc);
- AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
- static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
- PP.EnterToken(AnnotTok, /*IsReinject=*/false);
- }
- /// Handle all MS pragmas. Simply forwards the tokens after inserting
- /// an annotation token.
- void PragmaMSPragma::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer, Token &Tok) {
- Token EoF, AnnotTok;
- EoF.startToken();
- EoF.setKind(tok::eof);
- AnnotTok.startToken();
- AnnotTok.setKind(tok::annot_pragma_ms_pragma);
- AnnotTok.setLocation(Tok.getLocation());
- AnnotTok.setAnnotationEndLoc(Tok.getLocation());
- SmallVector<Token, 8> TokenVector;
- // Suck up all of the tokens before the eod.
- for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
- TokenVector.push_back(Tok);
- AnnotTok.setAnnotationEndLoc(Tok.getLocation());
- }
- // Add a sentinel EoF token to the end of the list.
- TokenVector.push_back(EoF);
- // We must allocate this array with new because EnterTokenStream is going to
- // delete it later.
- markAsReinjectedForRelexing(TokenVector);
- auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
- std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
- auto Value = new (PP.getPreprocessorAllocator())
- std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
- TokenVector.size());
- AnnotTok.setAnnotationValue(Value);
- PP.EnterToken(AnnotTok, /*IsReinject*/ false);
- }
- /// Handle the \#pragma float_control extension.
- ///
- /// The syntax is:
- /// \code
- /// #pragma float_control(keyword[, setting] [,push])
- /// \endcode
- /// Where 'keyword' and 'setting' are identifiers.
- // 'keyword' can be: precise, except, push, pop
- // 'setting' can be: on, off
- /// The optional arguments 'setting' and 'push' are supported only
- /// when the keyword is 'precise' or 'except'.
- void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- Sema::PragmaMsStackAction Action = Sema::PSK_Set;
- SourceLocation FloatControlLoc = Tok.getLocation();
- Token PragmaName = Tok;
- if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
- << PragmaName.getIdentifierInfo()->getName();
- return;
- }
- PP.Lex(Tok);
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
- return;
- }
- // Read the identifier.
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
- return;
- }
- // Verify that this is one of the float control options.
- IdentifierInfo *II = Tok.getIdentifierInfo();
- PragmaFloatControlKind Kind =
- llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
- .Case("precise", PFC_Precise)
- .Case("except", PFC_Except)
- .Case("push", PFC_Push)
- .Case("pop", PFC_Pop)
- .Default(PFC_Unknown);
- PP.Lex(Tok); // the identifier
- if (Kind == PFC_Unknown) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
- return;
- } else if (Kind == PFC_Push || Kind == PFC_Pop) {
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
- return;
- }
- PP.Lex(Tok); // Eat the r_paren
- Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;
- } else {
- if (Tok.is(tok::r_paren))
- // Selecting Precise or Except
- PP.Lex(Tok); // the r_paren
- else if (Tok.isNot(tok::comma)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
- return;
- } else {
- PP.Lex(Tok); // ,
- if (!Tok.isAnyIdentifier()) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
- return;
- }
- StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
- if (PushOnOff == "on")
- // Kind is set correctly
- ;
- else if (PushOnOff == "off") {
- if (Kind == PFC_Precise)
- Kind = PFC_NoPrecise;
- if (Kind == PFC_Except)
- Kind = PFC_NoExcept;
- } else if (PushOnOff == "push") {
- Action = Sema::PSK_Push_Set;
- } else {
- PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
- return;
- }
- PP.Lex(Tok); // the identifier
- if (Tok.is(tok::comma)) {
- PP.Lex(Tok); // ,
- if (!Tok.isAnyIdentifier()) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
- return;
- }
- StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
- if (ExpectedPush == "push") {
- Action = Sema::PSK_Push_Set;
- } else {
- PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
- return;
- }
- PP.Lex(Tok); // the push identifier
- }
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
- return;
- }
- PP.Lex(Tok); // the r_paren
- }
- }
- SourceLocation EndLoc = Tok.getLocation();
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "float_control";
- return;
- }
- // Note: there is no accomodation for PP callback for this pragma.
- // Enter the annotation.
- auto TokenArray = std::make_unique<Token[]>(1);
- TokenArray[0].startToken();
- TokenArray[0].setKind(tok::annot_pragma_float_control);
- TokenArray[0].setLocation(FloatControlLoc);
- TokenArray[0].setAnnotationEndLoc(EndLoc);
- // Create an encoding of Action and Value by shifting the Action into
- // the high 16 bits then union with the Kind.
- TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
- static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
- PP.EnterTokenStream(std::move(TokenArray), 1,
- /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
- }
- /// Handle the Microsoft \#pragma detect_mismatch extension.
- ///
- /// The syntax is:
- /// \code
- /// #pragma detect_mismatch("name", "value")
- /// \endcode
- /// Where 'name' and 'value' are quoted strings. The values are embedded in
- /// the object file and passed along to the linker. If the linker detects a
- /// mismatch in the object file's values for the given name, a LNK2038 error
- /// is emitted. See MSDN for more details.
- void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- SourceLocation DetectMismatchLoc = Tok.getLocation();
- PP.Lex(Tok);
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
- return;
- }
- // Read the name to embed, which must be a string literal.
- std::string NameString;
- if (!PP.LexStringLiteral(Tok, NameString,
- "pragma detect_mismatch",
- /*AllowMacroExpansion=*/true))
- return;
- // Read the comma followed by a second string literal.
- std::string ValueString;
- if (Tok.isNot(tok::comma)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
- return;
- }
- if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
- /*AllowMacroExpansion=*/true))
- return;
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
- return;
- }
- PP.Lex(Tok); // Eat the r_paren.
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
- return;
- }
- // If the pragma is lexically sound, notify any interested PPCallbacks.
- if (PP.getPPCallbacks())
- PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
- ValueString);
- Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
- }
- /// Handle the microsoft \#pragma comment extension.
- ///
- /// The syntax is:
- /// \code
- /// #pragma comment(linker, "foo")
- /// \endcode
- /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
- /// "foo" is a string, which is fully macro expanded, and permits string
- /// concatenation, embedded escape characters etc. See MSDN for more details.
- void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- SourceLocation CommentLoc = Tok.getLocation();
- PP.Lex(Tok);
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
- return;
- }
- // Read the identifier.
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
- return;
- }
- // Verify that this is one of the 5 explicitly listed options.
- IdentifierInfo *II = Tok.getIdentifierInfo();
- PragmaMSCommentKind Kind =
- llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
- .Case("linker", PCK_Linker)
- .Case("lib", PCK_Lib)
- .Case("compiler", PCK_Compiler)
- .Case("exestr", PCK_ExeStr)
- .Case("user", PCK_User)
- .Default(PCK_Unknown);
- if (Kind == PCK_Unknown) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
- return;
- }
- if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
- << II->getName();
- return;
- }
- // Read the optional string if present.
- PP.Lex(Tok);
- std::string ArgumentString;
- if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
- "pragma comment",
- /*AllowMacroExpansion=*/true))
- return;
- // FIXME: warn that 'exestr' is deprecated.
- // FIXME: If the kind is "compiler" warn if the string is present (it is
- // ignored).
- // The MSDN docs say that "lib" and "linker" require a string and have a short
- // list of linker options they support, but in practice MSVC doesn't
- // issue a diagnostic. Therefore neither does clang.
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
- return;
- }
- PP.Lex(Tok); // eat the r_paren.
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
- return;
- }
- // If the pragma is lexically sound, notify any interested PPCallbacks.
- if (PP.getPPCallbacks())
- PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
- Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
- }
- // #pragma clang optimize off
- // #pragma clang optimize on
- void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &FirstToken) {
- Token Tok;
- PP.Lex(Tok);
- if (Tok.is(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
- << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
- return;
- }
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
- << PP.getSpelling(Tok);
- return;
- }
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- // The only accepted values are 'on' or 'off'.
- bool IsOn = false;
- if (II->isStr("on")) {
- IsOn = true;
- } else if (!II->isStr("off")) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
- << PP.getSpelling(Tok);
- return;
- }
- PP.Lex(Tok);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
- << PP.getSpelling(Tok);
- return;
- }
- Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
- }
- namespace {
- /// Used as the annotation value for tok::annot_pragma_fp.
- struct TokFPAnnotValue {
- enum FlagKinds { Contract, Reassociate, Exceptions, EvalMethod };
- enum FlagValues { On, Off, Fast };
- std::optional<LangOptions::FPModeKind> ContractValue;
- std::optional<LangOptions::FPModeKind> ReassociateValue;
- std::optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
- std::optional<LangOptions::FPEvalMethodKind> EvalMethodValue;
- };
- } // end anonymous namespace
- void PragmaFPHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer, Token &Tok) {
- // fp
- Token PragmaName = Tok;
- SmallVector<Token, 1> TokenList;
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
- << /*MissingOption=*/true << "";
- return;
- }
- auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;
- while (Tok.is(tok::identifier)) {
- IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
- auto FlagKind =
- llvm::StringSwitch<std::optional<TokFPAnnotValue::FlagKinds>>(
- OptionInfo->getName())
- .Case("contract", TokFPAnnotValue::Contract)
- .Case("reassociate", TokFPAnnotValue::Reassociate)
- .Case("exceptions", TokFPAnnotValue::Exceptions)
- .Case("eval_method", TokFPAnnotValue::EvalMethod)
- .Default(std::nullopt);
- if (!FlagKind) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
- << /*MissingOption=*/false << OptionInfo;
- return;
- }
- PP.Lex(Tok);
- // Read '('
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
- return;
- }
- PP.Lex(Tok);
- bool isEvalMethodDouble =
- Tok.is(tok::kw_double) && FlagKind == TokFPAnnotValue::EvalMethod;
- // Don't diagnose if we have an eval_metod pragma with "double" kind.
- if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
- << PP.getSpelling(Tok) << OptionInfo->getName()
- << static_cast<int>(*FlagKind);
- return;
- }
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- if (FlagKind == TokFPAnnotValue::Contract) {
- AnnotValue->ContractValue =
- llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
- II->getName())
- .Case("on", LangOptions::FPModeKind::FPM_On)
- .Case("off", LangOptions::FPModeKind::FPM_Off)
- .Case("fast", LangOptions::FPModeKind::FPM_Fast)
- .Default(std::nullopt);
- if (!AnnotValue->ContractValue) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
- << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
- return;
- }
- } else if (FlagKind == TokFPAnnotValue::Reassociate) {
- AnnotValue->ReassociateValue =
- llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
- II->getName())
- .Case("on", LangOptions::FPModeKind::FPM_On)
- .Case("off", LangOptions::FPModeKind::FPM_Off)
- .Default(std::nullopt);
- if (!AnnotValue->ReassociateValue) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
- << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
- return;
- }
- } else if (FlagKind == TokFPAnnotValue::Exceptions) {
- AnnotValue->ExceptionsValue =
- llvm::StringSwitch<std::optional<LangOptions::FPExceptionModeKind>>(
- II->getName())
- .Case("ignore", LangOptions::FPE_Ignore)
- .Case("maytrap", LangOptions::FPE_MayTrap)
- .Case("strict", LangOptions::FPE_Strict)
- .Default(std::nullopt);
- if (!AnnotValue->ExceptionsValue) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
- << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
- return;
- }
- } else if (FlagKind == TokFPAnnotValue::EvalMethod) {
- AnnotValue->EvalMethodValue =
- llvm::StringSwitch<std::optional<LangOptions::FPEvalMethodKind>>(
- II->getName())
- .Case("source", LangOptions::FPEvalMethodKind::FEM_Source)
- .Case("double", LangOptions::FPEvalMethodKind::FEM_Double)
- .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended)
- .Default(std::nullopt);
- if (!AnnotValue->EvalMethodValue) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
- << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
- return;
- }
- }
- PP.Lex(Tok);
- // Read ')'
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
- return;
- }
- PP.Lex(Tok);
- }
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "clang fp";
- return;
- }
- Token FPTok;
- FPTok.startToken();
- FPTok.setKind(tok::annot_pragma_fp);
- FPTok.setLocation(PragmaName.getLocation());
- FPTok.setAnnotationEndLoc(PragmaName.getLocation());
- FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
- TokenList.push_back(FPTok);
- auto TokenArray = std::make_unique<Token[]>(TokenList.size());
- std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
- PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
- /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
- }
- void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- Token PragmaName = Tok;
- SmallVector<Token, 1> TokenList;
- if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
- << PragmaName.getIdentifierInfo()->getName();
- return;
- }
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
- << PragmaName.getIdentifierInfo()->getName();
- return;
- }
- IdentifierInfo *II = Tok.getIdentifierInfo();
- auto RM =
- llvm::StringSwitch<llvm::RoundingMode>(II->getName())
- .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)
- .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)
- .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)
- .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)
- .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)
- .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)
- .Default(llvm::RoundingMode::Invalid);
- if (RM == llvm::RoundingMode::Invalid) {
- PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);
- return;
- }
- PP.Lex(Tok);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "STDC FENV_ROUND";
- return;
- }
- // Until the pragma is fully implemented, issue a warning.
- PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
- MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
- 1);
- Toks[0].startToken();
- Toks[0].setKind(tok::annot_pragma_fenv_round);
- Toks[0].setLocation(Tok.getLocation());
- Toks[0].setAnnotationEndLoc(Tok.getLocation());
- Toks[0].setAnnotationValue(
- reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));
- PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
- /*IsReinject=*/false);
- }
- void Parser::HandlePragmaFP() {
- assert(Tok.is(tok::annot_pragma_fp));
- auto *AnnotValue =
- reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
- if (AnnotValue->ReassociateValue)
- Actions.ActOnPragmaFPReassociate(Tok.getLocation(),
- *AnnotValue->ReassociateValue ==
- LangOptions::FPModeKind::FPM_On);
- if (AnnotValue->ContractValue)
- Actions.ActOnPragmaFPContract(Tok.getLocation(),
- *AnnotValue->ContractValue);
- if (AnnotValue->ExceptionsValue)
- Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
- *AnnotValue->ExceptionsValue);
- if (AnnotValue->EvalMethodValue)
- Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(),
- *AnnotValue->EvalMethodValue);
- ConsumeAnnotationToken();
- }
- /// Parses loop or unroll pragma hint value and fills in Info.
- static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
- Token Option, bool ValueInParens,
- PragmaLoopHintInfo &Info) {
- SmallVector<Token, 1> ValueList;
- int OpenParens = ValueInParens ? 1 : 0;
- // Read constant expression.
- while (Tok.isNot(tok::eod)) {
- if (Tok.is(tok::l_paren))
- OpenParens++;
- else if (Tok.is(tok::r_paren)) {
- OpenParens--;
- if (OpenParens == 0 && ValueInParens)
- break;
- }
- ValueList.push_back(Tok);
- PP.Lex(Tok);
- }
- if (ValueInParens) {
- // Read ')'
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
- return true;
- }
- PP.Lex(Tok);
- }
- Token EOFTok;
- EOFTok.startToken();
- EOFTok.setKind(tok::eof);
- EOFTok.setLocation(Tok.getLocation());
- ValueList.push_back(EOFTok); // Terminates expression for parsing.
- markAsReinjectedForRelexing(ValueList);
- Info.Toks = llvm::ArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
- Info.PragmaName = PragmaName;
- Info.Option = Option;
- return false;
- }
- /// Handle the \#pragma clang loop directive.
- /// #pragma clang 'loop' loop-hints
- ///
- /// loop-hints:
- /// loop-hint loop-hints[opt]
- ///
- /// loop-hint:
- /// 'vectorize' '(' loop-hint-keyword ')'
- /// 'interleave' '(' loop-hint-keyword ')'
- /// 'unroll' '(' unroll-hint-keyword ')'
- /// 'vectorize_predicate' '(' loop-hint-keyword ')'
- /// 'vectorize_width' '(' loop-hint-value ')'
- /// 'interleave_count' '(' loop-hint-value ')'
- /// 'unroll_count' '(' loop-hint-value ')'
- /// 'pipeline' '(' disable ')'
- /// 'pipeline_initiation_interval' '(' loop-hint-value ')'
- ///
- /// loop-hint-keyword:
- /// 'enable'
- /// 'disable'
- /// 'assume_safety'
- ///
- /// unroll-hint-keyword:
- /// 'enable'
- /// 'disable'
- /// 'full'
- ///
- /// loop-hint-value:
- /// constant-expression
- ///
- /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
- /// try vectorizing the instructions of the loop it precedes. Specifying
- /// interleave(enable) or interleave_count(_value_) instructs llvm to try
- /// interleaving multiple iterations of the loop it precedes. The width of the
- /// vector instructions is specified by vectorize_width() and the number of
- /// interleaved loop iterations is specified by interleave_count(). Specifying a
- /// value of 1 effectively disables vectorization/interleaving, even if it is
- /// possible and profitable, and 0 is invalid. The loop vectorizer currently
- /// only works on inner loops.
- ///
- /// The unroll and unroll_count directives control the concatenation
- /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
- /// completely if the trip count is known at compile time and unroll partially
- /// if the trip count is not known. Specifying unroll(full) is similar to
- /// unroll(enable) but will unroll the loop only if the trip count is known at
- /// compile time. Specifying unroll(disable) disables unrolling for the
- /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
- /// loop the number of times indicated by the value.
- void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- // Incoming token is "loop" from "#pragma clang loop".
- Token PragmaName = Tok;
- SmallVector<Token, 1> TokenList;
- // Lex the optimization option and verify it is an identifier.
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
- << /*MissingOption=*/true << "";
- return;
- }
- while (Tok.is(tok::identifier)) {
- Token Option = Tok;
- IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
- bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
- .Case("vectorize", true)
- .Case("interleave", true)
- .Case("unroll", true)
- .Case("distribute", true)
- .Case("vectorize_predicate", true)
- .Case("vectorize_width", true)
- .Case("interleave_count", true)
- .Case("unroll_count", true)
- .Case("pipeline", true)
- .Case("pipeline_initiation_interval", true)
- .Default(false);
- if (!OptionValid) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
- << /*MissingOption=*/false << OptionInfo;
- return;
- }
- PP.Lex(Tok);
- // Read '('
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
- return;
- }
- PP.Lex(Tok);
- auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
- if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
- *Info))
- return;
- // Generate the loop hint token.
- Token LoopHintTok;
- LoopHintTok.startToken();
- LoopHintTok.setKind(tok::annot_pragma_loop_hint);
- LoopHintTok.setLocation(Introducer.Loc);
- LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
- LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
- TokenList.push_back(LoopHintTok);
- }
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "clang loop";
- return;
- }
- auto TokenArray = std::make_unique<Token[]>(TokenList.size());
- std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
- PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
- /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
- }
- /// Handle the loop unroll optimization pragmas.
- /// #pragma unroll
- /// #pragma unroll unroll-hint-value
- /// #pragma unroll '(' unroll-hint-value ')'
- /// #pragma nounroll
- /// #pragma unroll_and_jam
- /// #pragma unroll_and_jam unroll-hint-value
- /// #pragma unroll_and_jam '(' unroll-hint-value ')'
- /// #pragma nounroll_and_jam
- ///
- /// unroll-hint-value:
- /// constant-expression
- ///
- /// Loop unrolling hints can be specified with '#pragma unroll' or
- /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
- /// contained in parentheses. With no argument the directive instructs llvm to
- /// try to unroll the loop completely. A positive integer argument can be
- /// specified to indicate the number of times the loop should be unrolled. To
- /// maximize compatibility with other compilers the unroll count argument can be
- /// specified with or without parentheses. Specifying, '#pragma nounroll'
- /// disables unrolling of the loop.
- void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
- // "#pragma nounroll".
- Token PragmaName = Tok;
- PP.Lex(Tok);
- auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
- if (Tok.is(tok::eod)) {
- // nounroll or unroll pragma without an argument.
- Info->PragmaName = PragmaName;
- Info->Option.startToken();
- } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
- PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << PragmaName.getIdentifierInfo()->getName();
- return;
- } else {
- // Unroll pragma with an argument: "#pragma unroll N" or
- // "#pragma unroll(N)".
- // Read '(' if it exists.
- bool ValueInParens = Tok.is(tok::l_paren);
- if (ValueInParens)
- PP.Lex(Tok);
- Token Option;
- Option.startToken();
- if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
- return;
- // In CUDA, the argument to '#pragma unroll' should not be contained in
- // parentheses.
- if (PP.getLangOpts().CUDA && ValueInParens)
- PP.Diag(Info->Toks[0].getLocation(),
- diag::warn_pragma_unroll_cuda_value_in_parens);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "unroll";
- return;
- }
- }
- // Generate the hint token.
- auto TokenArray = std::make_unique<Token[]>(1);
- TokenArray[0].startToken();
- TokenArray[0].setKind(tok::annot_pragma_loop_hint);
- TokenArray[0].setLocation(Introducer.Loc);
- TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
- TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
- PP.EnterTokenStream(std::move(TokenArray), 1,
- /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
- }
- /// Handle the Microsoft \#pragma intrinsic extension.
- ///
- /// The syntax is:
- /// \code
- /// #pragma intrinsic(memset)
- /// #pragma intrinsic(strlen, memcpy)
- /// \endcode
- ///
- /// Pragma intrisic tells the compiler to use a builtin version of the
- /// function. Clang does it anyway, so the pragma doesn't really do anything.
- /// Anyway, we emit a warning if the function specified in \#pragma intrinsic
- /// isn't an intrinsic in clang and suggest to include intrin.h.
- void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- PP.Lex(Tok);
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
- << "intrinsic";
- return;
- }
- PP.Lex(Tok);
- bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
- while (Tok.is(tok::identifier)) {
- IdentifierInfo *II = Tok.getIdentifierInfo();
- if (!II->getBuiltinID())
- PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
- << II << SuggestIntrinH;
- PP.Lex(Tok);
- if (Tok.isNot(tok::comma))
- break;
- PP.Lex(Tok);
- }
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
- << "intrinsic";
- return;
- }
- PP.Lex(Tok);
- if (Tok.isNot(tok::eod))
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "intrinsic";
- }
- bool Parser::HandlePragmaMSFunction(StringRef PragmaName,
- SourceLocation PragmaLocation) {
- Token FirstTok = Tok;
- if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
- PragmaName))
- return false;
- bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
- llvm::SmallVector<StringRef> NoBuiltins;
- while (Tok.is(tok::identifier)) {
- IdentifierInfo *II = Tok.getIdentifierInfo();
- if (!II->getBuiltinID())
- PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
- << II << SuggestIntrinH;
- else
- NoBuiltins.emplace_back(II->getName());
- PP.Lex(Tok);
- if (Tok.isNot(tok::comma))
- break;
- PP.Lex(Tok); // ,
- }
- if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
- PragmaName) ||
- ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
- PragmaName))
- return false;
- Actions.ActOnPragmaMSFunction(FirstTok.getLocation(), NoBuiltins);
- return true;
- }
- // #pragma optimize("gsty", on|off)
- bool Parser::HandlePragmaMSOptimize(StringRef PragmaName,
- SourceLocation PragmaLocation) {
- Token FirstTok = Tok;
- if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
- PragmaName))
- return false;
- if (Tok.isNot(tok::string_literal)) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_string) << PragmaName;
- return false;
- }
- ExprResult StringResult = ParseStringLiteralExpression();
- if (StringResult.isInvalid())
- return false; // Already diagnosed.
- StringLiteral *OptimizationList = cast<StringLiteral>(StringResult.get());
- if (OptimizationList->getCharByteWidth() != 1) {
- PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
- << PragmaName;
- return false;
- }
- if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
- PragmaName))
- return false;
- if (Tok.is(tok::eof) || Tok.is(tok::r_paren)) {
- PP.Diag(PragmaLocation, diag::warn_pragma_missing_argument)
- << PragmaName << /*Expected=*/true << "'on' or 'off'";
- return false;
- }
- IdentifierInfo *II = Tok.getIdentifierInfo();
- if (!II || (!II->isStr("on") && !II->isStr("off"))) {
- PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
- << PP.getSpelling(Tok) << PragmaName << /*Expected=*/true
- << "'on' or 'off'";
- return false;
- }
- bool IsOn = II->isStr("on");
- PP.Lex(Tok);
- if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
- PragmaName))
- return false;
- // TODO: Add support for "sgty"
- if (!OptimizationList->getString().empty()) {
- PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
- << OptimizationList->getString() << PragmaName << /*Expected=*/true
- << "\"\"";
- return false;
- }
- if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
- PragmaName))
- return false;
- Actions.ActOnPragmaMSOptimize(FirstTok.getLocation(), IsOn);
- return true;
- }
- void PragmaForceCUDAHostDeviceHandler::HandlePragma(
- Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
- Token FirstTok = Tok;
- PP.Lex(Tok);
- IdentifierInfo *Info = Tok.getIdentifierInfo();
- if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
- PP.Diag(FirstTok.getLocation(),
- diag::warn_pragma_force_cuda_host_device_bad_arg);
- return;
- }
- if (Info->isStr("begin"))
- Actions.PushForceCUDAHostDevice();
- else if (!Actions.PopForceCUDAHostDevice())
- PP.Diag(FirstTok.getLocation(),
- diag::err_pragma_cannot_end_force_cuda_host_device);
- PP.Lex(Tok);
- if (!Tok.is(tok::eod))
- PP.Diag(FirstTok.getLocation(),
- diag::warn_pragma_force_cuda_host_device_bad_arg);
- }
- /// Handle the #pragma clang attribute directive.
- ///
- /// The syntax is:
- /// \code
- /// #pragma clang attribute push (attribute, subject-set)
- /// #pragma clang attribute push
- /// #pragma clang attribute (attribute, subject-set)
- /// #pragma clang attribute pop
- /// \endcode
- ///
- /// There are also 'namespace' variants of push and pop directives. The bare
- /// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
- /// namespace, since it always applies attributes to the most recently pushed
- /// group, regardless of namespace.
- /// \code
- /// #pragma clang attribute namespace.push (attribute, subject-set)
- /// #pragma clang attribute namespace.push
- /// #pragma clang attribute namespace.pop
- /// \endcode
- ///
- /// The subject-set clause defines the set of declarations which receive the
- /// attribute. Its exact syntax is described in the LanguageExtensions document
- /// in Clang's documentation.
- ///
- /// This directive instructs the compiler to begin/finish applying the specified
- /// attribute to the set of attribute-specific declarations in the active range
- /// of the pragma.
- void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &FirstToken) {
- Token Tok;
- PP.Lex(Tok);
- auto *Info = new (PP.getPreprocessorAllocator())
- PragmaAttributeInfo(AttributesForPragmaAttribute);
- // Parse the optional namespace followed by a period.
- if (Tok.is(tok::identifier)) {
- IdentifierInfo *II = Tok.getIdentifierInfo();
- if (!II->isStr("push") && !II->isStr("pop")) {
- Info->Namespace = II;
- PP.Lex(Tok);
- if (!Tok.is(tok::period)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
- << II;
- return;
- }
- PP.Lex(Tok);
- }
- }
- if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
- PP.Diag(Tok.getLocation(),
- diag::err_pragma_attribute_expected_push_pop_paren);
- return;
- }
- // Determine what action this pragma clang attribute represents.
- if (Tok.is(tok::l_paren)) {
- if (Info->Namespace) {
- PP.Diag(Tok.getLocation(),
- diag::err_pragma_attribute_namespace_on_attribute);
- PP.Diag(Tok.getLocation(),
- diag::note_pragma_attribute_namespace_on_attribute);
- return;
- }
- Info->Action = PragmaAttributeInfo::Attribute;
- } else {
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- if (II->isStr("push"))
- Info->Action = PragmaAttributeInfo::Push;
- else if (II->isStr("pop"))
- Info->Action = PragmaAttributeInfo::Pop;
- else {
- PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
- << PP.getSpelling(Tok);
- return;
- }
- PP.Lex(Tok);
- }
- // Parse the actual attribute.
- if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
- Info->Action == PragmaAttributeInfo::Attribute) {
- if (Tok.isNot(tok::l_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
- return;
- }
- PP.Lex(Tok);
- // Lex the attribute tokens.
- SmallVector<Token, 16> AttributeTokens;
- int OpenParens = 1;
- while (Tok.isNot(tok::eod)) {
- if (Tok.is(tok::l_paren))
- OpenParens++;
- else if (Tok.is(tok::r_paren)) {
- OpenParens--;
- if (OpenParens == 0)
- break;
- }
- AttributeTokens.push_back(Tok);
- PP.Lex(Tok);
- }
- if (AttributeTokens.empty()) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
- return;
- }
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
- return;
- }
- SourceLocation EndLoc = Tok.getLocation();
- PP.Lex(Tok);
- // Terminate the attribute for parsing.
- Token EOFTok;
- EOFTok.startToken();
- EOFTok.setKind(tok::eof);
- EOFTok.setLocation(EndLoc);
- AttributeTokens.push_back(EOFTok);
- markAsReinjectedForRelexing(AttributeTokens);
- Info->Tokens =
- llvm::ArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
- }
- if (Tok.isNot(tok::eod))
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "clang attribute";
- // Generate the annotated pragma token.
- auto TokenArray = std::make_unique<Token[]>(1);
- TokenArray[0].startToken();
- TokenArray[0].setKind(tok::annot_pragma_attribute);
- TokenArray[0].setLocation(FirstToken.getLocation());
- TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
- TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
- PP.EnterTokenStream(std::move(TokenArray), 1,
- /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
- }
- // Handle '#pragma clang max_tokens 12345'.
- void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- PP.Lex(Tok);
- if (Tok.is(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
- << "clang max_tokens_here" << /*Expected=*/true << "integer";
- return;
- }
- SourceLocation Loc = Tok.getLocation();
- uint64_t MaxTokens;
- if (Tok.isNot(tok::numeric_constant) ||
- !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
- << "clang max_tokens_here";
- return;
- }
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "clang max_tokens_here";
- return;
- }
- if (PP.getTokenCount() > MaxTokens) {
- PP.Diag(Loc, diag::warn_max_tokens)
- << PP.getTokenCount() << (unsigned)MaxTokens;
- }
- }
- // Handle '#pragma clang max_tokens_total 12345'.
- void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &Tok) {
- PP.Lex(Tok);
- if (Tok.is(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
- << "clang max_tokens_total" << /*Expected=*/true << "integer";
- return;
- }
- SourceLocation Loc = Tok.getLocation();
- uint64_t MaxTokens;
- if (Tok.isNot(tok::numeric_constant) ||
- !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
- << "clang max_tokens_total";
- return;
- }
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "clang max_tokens_total";
- return;
- }
- PP.overrideMaxTokens(MaxTokens, Loc);
- }
- // Handle '#pragma clang riscv intrinsic vector'.
- void PragmaRISCVHandler::HandlePragma(Preprocessor &PP,
- PragmaIntroducer Introducer,
- Token &FirstToken) {
- Token Tok;
- PP.Lex(Tok);
- IdentifierInfo *II = Tok.getIdentifierInfo();
- if (!II || !II->isStr("intrinsic")) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
- << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'";
- return;
- }
- PP.Lex(Tok);
- II = Tok.getIdentifierInfo();
- if (!II || !II->isStr("vector")) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
- << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'vector'";
- return;
- }
- PP.Lex(Tok);
- if (Tok.isNot(tok::eod)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "clang riscv intrinsic";
- return;
- }
- Actions.DeclareRISCVVBuiltins = true;
- }
|