ParsePragma.cpp 138 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037
  1. //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements the language specific #pragma handlers.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "clang/AST/ASTContext.h"
  13. #include "clang/Basic/PragmaKinds.h"
  14. #include "clang/Basic/TargetInfo.h"
  15. #include "clang/Lex/Preprocessor.h"
  16. #include "clang/Lex/Token.h"
  17. #include "clang/Parse/LoopHint.h"
  18. #include "clang/Parse/ParseDiagnostic.h"
  19. #include "clang/Parse/Parser.h"
  20. #include "clang/Parse/RAIIObjectsForParser.h"
  21. #include "clang/Sema/Scope.h"
  22. #include "llvm/ADT/ArrayRef.h"
  23. #include "llvm/ADT/StringSwitch.h"
  24. #include <optional>
  25. using namespace clang;
  26. namespace {
  27. struct PragmaAlignHandler : public PragmaHandler {
  28. explicit PragmaAlignHandler() : PragmaHandler("align") {}
  29. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  30. Token &FirstToken) override;
  31. };
  32. struct PragmaGCCVisibilityHandler : public PragmaHandler {
  33. explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
  34. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  35. Token &FirstToken) override;
  36. };
  37. struct PragmaOptionsHandler : public PragmaHandler {
  38. explicit PragmaOptionsHandler() : PragmaHandler("options") {}
  39. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  40. Token &FirstToken) override;
  41. };
  42. struct PragmaPackHandler : public PragmaHandler {
  43. explicit PragmaPackHandler() : PragmaHandler("pack") {}
  44. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  45. Token &FirstToken) override;
  46. };
  47. struct PragmaClangSectionHandler : public PragmaHandler {
  48. explicit PragmaClangSectionHandler(Sema &S)
  49. : PragmaHandler("section"), Actions(S) {}
  50. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  51. Token &FirstToken) override;
  52. private:
  53. Sema &Actions;
  54. };
  55. struct PragmaMSStructHandler : public PragmaHandler {
  56. explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
  57. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  58. Token &FirstToken) override;
  59. };
  60. struct PragmaUnusedHandler : public PragmaHandler {
  61. PragmaUnusedHandler() : PragmaHandler("unused") {}
  62. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  63. Token &FirstToken) override;
  64. };
  65. struct PragmaWeakHandler : public PragmaHandler {
  66. explicit PragmaWeakHandler() : PragmaHandler("weak") {}
  67. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  68. Token &FirstToken) override;
  69. };
  70. struct PragmaRedefineExtnameHandler : public PragmaHandler {
  71. explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
  72. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  73. Token &FirstToken) override;
  74. };
  75. struct PragmaOpenCLExtensionHandler : public PragmaHandler {
  76. PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
  77. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  78. Token &FirstToken) override;
  79. };
  80. struct PragmaFPContractHandler : public PragmaHandler {
  81. PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
  82. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  83. Token &FirstToken) override;
  84. };
  85. // Pragma STDC implementations.
  86. /// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
  87. struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
  88. PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
  89. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  90. Token &Tok) override {
  91. Token PragmaName = Tok;
  92. if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
  93. PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
  94. << PragmaName.getIdentifierInfo()->getName();
  95. return;
  96. }
  97. tok::OnOffSwitch OOS;
  98. if (PP.LexOnOffSwitch(OOS))
  99. return;
  100. MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
  101. 1);
  102. Toks[0].startToken();
  103. Toks[0].setKind(tok::annot_pragma_fenv_access);
  104. Toks[0].setLocation(Tok.getLocation());
  105. Toks[0].setAnnotationEndLoc(Tok.getLocation());
  106. Toks[0].setAnnotationValue(reinterpret_cast<void*>(
  107. static_cast<uintptr_t>(OOS)));
  108. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  109. /*IsReinject=*/false);
  110. }
  111. };
  112. /// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
  113. struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
  114. PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
  115. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  116. Token &Tok) override {
  117. tok::OnOffSwitch OOS;
  118. PP.LexOnOffSwitch(OOS);
  119. }
  120. };
  121. /// Handler for "\#pragma STDC FENV_ROUND ...".
  122. struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler {
  123. PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}
  124. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  125. Token &Tok) override;
  126. };
  127. /// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
  128. struct PragmaSTDC_UnknownHandler : public PragmaHandler {
  129. PragmaSTDC_UnknownHandler() = default;
  130. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  131. Token &UnknownTok) override {
  132. // C99 6.10.6p2, unknown forms are not allowed.
  133. PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
  134. }
  135. };
  136. struct PragmaFPHandler : public PragmaHandler {
  137. PragmaFPHandler() : PragmaHandler("fp") {}
  138. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  139. Token &FirstToken) override;
  140. };
  141. struct PragmaNoOpenMPHandler : public PragmaHandler {
  142. PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
  143. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  144. Token &FirstToken) override;
  145. };
  146. struct PragmaOpenMPHandler : public PragmaHandler {
  147. PragmaOpenMPHandler() : PragmaHandler("omp") { }
  148. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  149. Token &FirstToken) override;
  150. };
  151. /// PragmaCommentHandler - "\#pragma comment ...".
  152. struct PragmaCommentHandler : public PragmaHandler {
  153. PragmaCommentHandler(Sema &Actions)
  154. : PragmaHandler("comment"), Actions(Actions) {}
  155. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  156. Token &FirstToken) override;
  157. private:
  158. Sema &Actions;
  159. };
  160. struct PragmaDetectMismatchHandler : public PragmaHandler {
  161. PragmaDetectMismatchHandler(Sema &Actions)
  162. : PragmaHandler("detect_mismatch"), Actions(Actions) {}
  163. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  164. Token &FirstToken) override;
  165. private:
  166. Sema &Actions;
  167. };
  168. struct PragmaFloatControlHandler : public PragmaHandler {
  169. PragmaFloatControlHandler(Sema &Actions)
  170. : PragmaHandler("float_control") {}
  171. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  172. Token &FirstToken) override;
  173. };
  174. struct PragmaMSPointersToMembers : public PragmaHandler {
  175. explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
  176. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  177. Token &FirstToken) override;
  178. };
  179. struct PragmaMSVtorDisp : public PragmaHandler {
  180. explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
  181. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  182. Token &FirstToken) override;
  183. };
  184. struct PragmaMSPragma : public PragmaHandler {
  185. explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
  186. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  187. Token &FirstToken) override;
  188. };
  189. /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
  190. struct PragmaOptimizeHandler : public PragmaHandler {
  191. PragmaOptimizeHandler(Sema &S)
  192. : PragmaHandler("optimize"), Actions(S) {}
  193. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  194. Token &FirstToken) override;
  195. private:
  196. Sema &Actions;
  197. };
  198. struct PragmaLoopHintHandler : public PragmaHandler {
  199. PragmaLoopHintHandler() : PragmaHandler("loop") {}
  200. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  201. Token &FirstToken) override;
  202. };
  203. struct PragmaUnrollHintHandler : public PragmaHandler {
  204. PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
  205. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  206. Token &FirstToken) override;
  207. };
  208. struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
  209. PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
  210. };
  211. struct PragmaMSIntrinsicHandler : public PragmaHandler {
  212. PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
  213. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  214. Token &FirstToken) override;
  215. };
  216. // "\#pragma fenv_access (on)".
  217. struct PragmaMSFenvAccessHandler : public PragmaHandler {
  218. PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {}
  219. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  220. Token &FirstToken) override {
  221. StringRef PragmaName = FirstToken.getIdentifierInfo()->getName();
  222. if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
  223. PP.Diag(FirstToken.getLocation(), diag::warn_pragma_fp_ignored)
  224. << PragmaName;
  225. return;
  226. }
  227. Token Tok;
  228. PP.Lex(Tok);
  229. if (Tok.isNot(tok::l_paren)) {
  230. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
  231. << PragmaName;
  232. return;
  233. }
  234. PP.Lex(Tok); // Consume the l_paren.
  235. if (Tok.isNot(tok::identifier)) {
  236. PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
  237. return;
  238. }
  239. const IdentifierInfo *II = Tok.getIdentifierInfo();
  240. tok::OnOffSwitch OOS;
  241. if (II->isStr("on")) {
  242. OOS = tok::OOS_ON;
  243. PP.Lex(Tok);
  244. } else if (II->isStr("off")) {
  245. OOS = tok::OOS_OFF;
  246. PP.Lex(Tok);
  247. } else {
  248. PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
  249. return;
  250. }
  251. if (Tok.isNot(tok::r_paren)) {
  252. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
  253. << PragmaName;
  254. return;
  255. }
  256. PP.Lex(Tok); // Consume the r_paren.
  257. if (Tok.isNot(tok::eod)) {
  258. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  259. << PragmaName;
  260. return;
  261. }
  262. MutableArrayRef<Token> Toks(
  263. PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
  264. Toks[0].startToken();
  265. Toks[0].setKind(tok::annot_pragma_fenv_access_ms);
  266. Toks[0].setLocation(FirstToken.getLocation());
  267. Toks[0].setAnnotationEndLoc(Tok.getLocation());
  268. Toks[0].setAnnotationValue(
  269. reinterpret_cast<void*>(static_cast<uintptr_t>(OOS)));
  270. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  271. /*IsReinject=*/false);
  272. }
  273. };
  274. struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
  275. PragmaForceCUDAHostDeviceHandler(Sema &Actions)
  276. : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
  277. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  278. Token &FirstToken) override;
  279. private:
  280. Sema &Actions;
  281. };
  282. /// PragmaAttributeHandler - "\#pragma clang attribute ...".
  283. struct PragmaAttributeHandler : public PragmaHandler {
  284. PragmaAttributeHandler(AttributeFactory &AttrFactory)
  285. : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
  286. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  287. Token &FirstToken) override;
  288. /// A pool of attributes that were parsed in \#pragma clang attribute.
  289. ParsedAttributes AttributesForPragmaAttribute;
  290. };
  291. struct PragmaMaxTokensHereHandler : public PragmaHandler {
  292. PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
  293. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  294. Token &FirstToken) override;
  295. };
  296. struct PragmaMaxTokensTotalHandler : public PragmaHandler {
  297. PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
  298. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  299. Token &FirstToken) override;
  300. };
  301. struct PragmaRISCVHandler : public PragmaHandler {
  302. PragmaRISCVHandler(Sema &Actions)
  303. : PragmaHandler("riscv"), Actions(Actions) {}
  304. void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
  305. Token &FirstToken) override;
  306. private:
  307. Sema &Actions;
  308. };
  309. void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) {
  310. for (auto &T : Toks)
  311. T.setFlag(clang::Token::IsReinjected);
  312. }
  313. } // end namespace
  314. void Parser::initializePragmaHandlers() {
  315. AlignHandler = std::make_unique<PragmaAlignHandler>();
  316. PP.AddPragmaHandler(AlignHandler.get());
  317. GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
  318. PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
  319. OptionsHandler = std::make_unique<PragmaOptionsHandler>();
  320. PP.AddPragmaHandler(OptionsHandler.get());
  321. PackHandler = std::make_unique<PragmaPackHandler>();
  322. PP.AddPragmaHandler(PackHandler.get());
  323. MSStructHandler = std::make_unique<PragmaMSStructHandler>();
  324. PP.AddPragmaHandler(MSStructHandler.get());
  325. UnusedHandler = std::make_unique<PragmaUnusedHandler>();
  326. PP.AddPragmaHandler(UnusedHandler.get());
  327. WeakHandler = std::make_unique<PragmaWeakHandler>();
  328. PP.AddPragmaHandler(WeakHandler.get());
  329. RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
  330. PP.AddPragmaHandler(RedefineExtnameHandler.get());
  331. FPContractHandler = std::make_unique<PragmaFPContractHandler>();
  332. PP.AddPragmaHandler("STDC", FPContractHandler.get());
  333. STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
  334. PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get());
  335. STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>();
  336. PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get());
  337. STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
  338. PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
  339. STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
  340. PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
  341. PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
  342. PP.AddPragmaHandler("clang", PCSectionHandler.get());
  343. if (getLangOpts().OpenCL) {
  344. OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
  345. PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
  346. PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
  347. }
  348. if (getLangOpts().OpenMP)
  349. OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
  350. else
  351. OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
  352. PP.AddPragmaHandler(OpenMPHandler.get());
  353. if (getLangOpts().MicrosoftExt ||
  354. getTargetInfo().getTriple().isOSBinFormatELF()) {
  355. MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
  356. PP.AddPragmaHandler(MSCommentHandler.get());
  357. }
  358. FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
  359. PP.AddPragmaHandler(FloatControlHandler.get());
  360. if (getLangOpts().MicrosoftExt) {
  361. MSDetectMismatchHandler =
  362. std::make_unique<PragmaDetectMismatchHandler>(Actions);
  363. PP.AddPragmaHandler(MSDetectMismatchHandler.get());
  364. MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
  365. PP.AddPragmaHandler(MSPointersToMembers.get());
  366. MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
  367. PP.AddPragmaHandler(MSVtorDisp.get());
  368. MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
  369. PP.AddPragmaHandler(MSInitSeg.get());
  370. MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
  371. PP.AddPragmaHandler(MSDataSeg.get());
  372. MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
  373. PP.AddPragmaHandler(MSBSSSeg.get());
  374. MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
  375. PP.AddPragmaHandler(MSConstSeg.get());
  376. MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
  377. PP.AddPragmaHandler(MSCodeSeg.get());
  378. MSSection = std::make_unique<PragmaMSPragma>("section");
  379. PP.AddPragmaHandler(MSSection.get());
  380. MSStrictGuardStackCheck =
  381. std::make_unique<PragmaMSPragma>("strict_gs_check");
  382. PP.AddPragmaHandler(MSStrictGuardStackCheck.get());
  383. MSFunction = std::make_unique<PragmaMSPragma>("function");
  384. PP.AddPragmaHandler(MSFunction.get());
  385. MSAllocText = std::make_unique<PragmaMSPragma>("alloc_text");
  386. PP.AddPragmaHandler(MSAllocText.get());
  387. MSOptimize = std::make_unique<PragmaMSPragma>("optimize");
  388. PP.AddPragmaHandler(MSOptimize.get());
  389. MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
  390. PP.AddPragmaHandler(MSRuntimeChecks.get());
  391. MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
  392. PP.AddPragmaHandler(MSIntrinsic.get());
  393. MSFenvAccess = std::make_unique<PragmaMSFenvAccessHandler>();
  394. PP.AddPragmaHandler(MSFenvAccess.get());
  395. }
  396. if (getLangOpts().CUDA) {
  397. CUDAForceHostDeviceHandler =
  398. std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
  399. PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
  400. }
  401. OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
  402. PP.AddPragmaHandler("clang", OptimizeHandler.get());
  403. LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
  404. PP.AddPragmaHandler("clang", LoopHintHandler.get());
  405. UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
  406. PP.AddPragmaHandler(UnrollHintHandler.get());
  407. PP.AddPragmaHandler("GCC", UnrollHintHandler.get());
  408. NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
  409. PP.AddPragmaHandler(NoUnrollHintHandler.get());
  410. PP.AddPragmaHandler("GCC", NoUnrollHintHandler.get());
  411. UnrollAndJamHintHandler =
  412. std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
  413. PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
  414. NoUnrollAndJamHintHandler =
  415. std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
  416. PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
  417. FPHandler = std::make_unique<PragmaFPHandler>();
  418. PP.AddPragmaHandler("clang", FPHandler.get());
  419. AttributePragmaHandler =
  420. std::make_unique<PragmaAttributeHandler>(AttrFactory);
  421. PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
  422. MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
  423. PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
  424. MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
  425. PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
  426. if (getTargetInfo().getTriple().isRISCV()) {
  427. RISCVPragmaHandler = std::make_unique<PragmaRISCVHandler>(Actions);
  428. PP.AddPragmaHandler("clang", RISCVPragmaHandler.get());
  429. }
  430. }
  431. void Parser::resetPragmaHandlers() {
  432. // Remove the pragma handlers we installed.
  433. PP.RemovePragmaHandler(AlignHandler.get());
  434. AlignHandler.reset();
  435. PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
  436. GCCVisibilityHandler.reset();
  437. PP.RemovePragmaHandler(OptionsHandler.get());
  438. OptionsHandler.reset();
  439. PP.RemovePragmaHandler(PackHandler.get());
  440. PackHandler.reset();
  441. PP.RemovePragmaHandler(MSStructHandler.get());
  442. MSStructHandler.reset();
  443. PP.RemovePragmaHandler(UnusedHandler.get());
  444. UnusedHandler.reset();
  445. PP.RemovePragmaHandler(WeakHandler.get());
  446. WeakHandler.reset();
  447. PP.RemovePragmaHandler(RedefineExtnameHandler.get());
  448. RedefineExtnameHandler.reset();
  449. if (getLangOpts().OpenCL) {
  450. PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
  451. OpenCLExtensionHandler.reset();
  452. PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
  453. }
  454. PP.RemovePragmaHandler(OpenMPHandler.get());
  455. OpenMPHandler.reset();
  456. if (getLangOpts().MicrosoftExt ||
  457. getTargetInfo().getTriple().isOSBinFormatELF()) {
  458. PP.RemovePragmaHandler(MSCommentHandler.get());
  459. MSCommentHandler.reset();
  460. }
  461. PP.RemovePragmaHandler("clang", PCSectionHandler.get());
  462. PCSectionHandler.reset();
  463. PP.RemovePragmaHandler(FloatControlHandler.get());
  464. FloatControlHandler.reset();
  465. if (getLangOpts().MicrosoftExt) {
  466. PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
  467. MSDetectMismatchHandler.reset();
  468. PP.RemovePragmaHandler(MSPointersToMembers.get());
  469. MSPointersToMembers.reset();
  470. PP.RemovePragmaHandler(MSVtorDisp.get());
  471. MSVtorDisp.reset();
  472. PP.RemovePragmaHandler(MSInitSeg.get());
  473. MSInitSeg.reset();
  474. PP.RemovePragmaHandler(MSDataSeg.get());
  475. MSDataSeg.reset();
  476. PP.RemovePragmaHandler(MSBSSSeg.get());
  477. MSBSSSeg.reset();
  478. PP.RemovePragmaHandler(MSConstSeg.get());
  479. MSConstSeg.reset();
  480. PP.RemovePragmaHandler(MSCodeSeg.get());
  481. MSCodeSeg.reset();
  482. PP.RemovePragmaHandler(MSSection.get());
  483. MSSection.reset();
  484. PP.RemovePragmaHandler(MSStrictGuardStackCheck.get());
  485. MSStrictGuardStackCheck.reset();
  486. PP.RemovePragmaHandler(MSFunction.get());
  487. MSFunction.reset();
  488. PP.RemovePragmaHandler(MSAllocText.get());
  489. MSAllocText.reset();
  490. PP.RemovePragmaHandler(MSRuntimeChecks.get());
  491. MSRuntimeChecks.reset();
  492. PP.RemovePragmaHandler(MSIntrinsic.get());
  493. MSIntrinsic.reset();
  494. PP.RemovePragmaHandler(MSOptimize.get());
  495. MSOptimize.reset();
  496. PP.RemovePragmaHandler(MSFenvAccess.get());
  497. MSFenvAccess.reset();
  498. }
  499. if (getLangOpts().CUDA) {
  500. PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
  501. CUDAForceHostDeviceHandler.reset();
  502. }
  503. PP.RemovePragmaHandler("STDC", FPContractHandler.get());
  504. FPContractHandler.reset();
  505. PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get());
  506. STDCFenvAccessHandler.reset();
  507. PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get());
  508. STDCFenvRoundHandler.reset();
  509. PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
  510. STDCCXLIMITHandler.reset();
  511. PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
  512. STDCUnknownHandler.reset();
  513. PP.RemovePragmaHandler("clang", OptimizeHandler.get());
  514. OptimizeHandler.reset();
  515. PP.RemovePragmaHandler("clang", LoopHintHandler.get());
  516. LoopHintHandler.reset();
  517. PP.RemovePragmaHandler(UnrollHintHandler.get());
  518. PP.RemovePragmaHandler("GCC", UnrollHintHandler.get());
  519. UnrollHintHandler.reset();
  520. PP.RemovePragmaHandler(NoUnrollHintHandler.get());
  521. PP.RemovePragmaHandler("GCC", NoUnrollHintHandler.get());
  522. NoUnrollHintHandler.reset();
  523. PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
  524. UnrollAndJamHintHandler.reset();
  525. PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
  526. NoUnrollAndJamHintHandler.reset();
  527. PP.RemovePragmaHandler("clang", FPHandler.get());
  528. FPHandler.reset();
  529. PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
  530. AttributePragmaHandler.reset();
  531. PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
  532. MaxTokensHerePragmaHandler.reset();
  533. PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
  534. MaxTokensTotalPragmaHandler.reset();
  535. if (getTargetInfo().getTriple().isRISCV()) {
  536. PP.RemovePragmaHandler("clang", RISCVPragmaHandler.get());
  537. RISCVPragmaHandler.reset();
  538. }
  539. }
  540. /// Handle the annotation token produced for #pragma unused(...)
  541. ///
  542. /// Each annot_pragma_unused is followed by the argument token so e.g.
  543. /// "#pragma unused(x,y)" becomes:
  544. /// annot_pragma_unused 'x' annot_pragma_unused 'y'
  545. void Parser::HandlePragmaUnused() {
  546. assert(Tok.is(tok::annot_pragma_unused));
  547. SourceLocation UnusedLoc = ConsumeAnnotationToken();
  548. Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
  549. ConsumeToken(); // The argument token.
  550. }
  551. void Parser::HandlePragmaVisibility() {
  552. assert(Tok.is(tok::annot_pragma_vis));
  553. const IdentifierInfo *VisType =
  554. static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
  555. SourceLocation VisLoc = ConsumeAnnotationToken();
  556. Actions.ActOnPragmaVisibility(VisType, VisLoc);
  557. }
  558. namespace {
  559. struct PragmaPackInfo {
  560. Sema::PragmaMsStackAction Action;
  561. StringRef SlotLabel;
  562. Token Alignment;
  563. };
  564. } // end anonymous namespace
  565. void Parser::HandlePragmaPack() {
  566. assert(Tok.is(tok::annot_pragma_pack));
  567. PragmaPackInfo *Info =
  568. static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
  569. SourceLocation PragmaLoc = Tok.getLocation();
  570. ExprResult Alignment;
  571. if (Info->Alignment.is(tok::numeric_constant)) {
  572. Alignment = Actions.ActOnNumericConstant(Info->Alignment);
  573. if (Alignment.isInvalid()) {
  574. ConsumeAnnotationToken();
  575. return;
  576. }
  577. }
  578. Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
  579. Alignment.get());
  580. // Consume the token after processing the pragma to enable pragma-specific
  581. // #include warnings.
  582. ConsumeAnnotationToken();
  583. }
  584. void Parser::HandlePragmaMSStruct() {
  585. assert(Tok.is(tok::annot_pragma_msstruct));
  586. PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
  587. reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
  588. Actions.ActOnPragmaMSStruct(Kind);
  589. ConsumeAnnotationToken();
  590. }
  591. void Parser::HandlePragmaAlign() {
  592. assert(Tok.is(tok::annot_pragma_align));
  593. Sema::PragmaOptionsAlignKind Kind =
  594. static_cast<Sema::PragmaOptionsAlignKind>(
  595. reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
  596. Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
  597. // Consume the token after processing the pragma to enable pragma-specific
  598. // #include warnings.
  599. ConsumeAnnotationToken();
  600. }
  601. void Parser::HandlePragmaDump() {
  602. assert(Tok.is(tok::annot_pragma_dump));
  603. IdentifierInfo *II =
  604. reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
  605. Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
  606. ConsumeAnnotationToken();
  607. }
  608. void Parser::HandlePragmaWeak() {
  609. assert(Tok.is(tok::annot_pragma_weak));
  610. SourceLocation PragmaLoc = ConsumeAnnotationToken();
  611. Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
  612. Tok.getLocation());
  613. ConsumeToken(); // The weak name.
  614. }
  615. void Parser::HandlePragmaWeakAlias() {
  616. assert(Tok.is(tok::annot_pragma_weakalias));
  617. SourceLocation PragmaLoc = ConsumeAnnotationToken();
  618. IdentifierInfo *WeakName = Tok.getIdentifierInfo();
  619. SourceLocation WeakNameLoc = Tok.getLocation();
  620. ConsumeToken();
  621. IdentifierInfo *AliasName = Tok.getIdentifierInfo();
  622. SourceLocation AliasNameLoc = Tok.getLocation();
  623. ConsumeToken();
  624. Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
  625. WeakNameLoc, AliasNameLoc);
  626. }
  627. void Parser::HandlePragmaRedefineExtname() {
  628. assert(Tok.is(tok::annot_pragma_redefine_extname));
  629. SourceLocation RedefLoc = ConsumeAnnotationToken();
  630. IdentifierInfo *RedefName = Tok.getIdentifierInfo();
  631. SourceLocation RedefNameLoc = Tok.getLocation();
  632. ConsumeToken();
  633. IdentifierInfo *AliasName = Tok.getIdentifierInfo();
  634. SourceLocation AliasNameLoc = Tok.getLocation();
  635. ConsumeToken();
  636. Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
  637. RedefNameLoc, AliasNameLoc);
  638. }
  639. void Parser::HandlePragmaFPContract() {
  640. assert(Tok.is(tok::annot_pragma_fp_contract));
  641. tok::OnOffSwitch OOS =
  642. static_cast<tok::OnOffSwitch>(
  643. reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
  644. LangOptions::FPModeKind FPC;
  645. switch (OOS) {
  646. case tok::OOS_ON:
  647. FPC = LangOptions::FPM_On;
  648. break;
  649. case tok::OOS_OFF:
  650. FPC = LangOptions::FPM_Off;
  651. break;
  652. case tok::OOS_DEFAULT:
  653. FPC = getLangOpts().getDefaultFPContractMode();
  654. break;
  655. }
  656. SourceLocation PragmaLoc = ConsumeAnnotationToken();
  657. Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
  658. }
  659. void Parser::HandlePragmaFloatControl() {
  660. assert(Tok.is(tok::annot_pragma_float_control));
  661. // The value that is held on the PragmaFloatControlStack encodes
  662. // the PragmaFloatControl kind and the MSStackAction kind
  663. // into a single 32-bit word. The MsStackAction is the high 16 bits
  664. // and the FloatControl is the lower 16 bits. Use shift and bit-and
  665. // to decode the parts.
  666. uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
  667. Sema::PragmaMsStackAction Action =
  668. static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
  669. PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);
  670. SourceLocation PragmaLoc = ConsumeAnnotationToken();
  671. Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
  672. }
  673. void Parser::HandlePragmaFEnvAccess() {
  674. assert(Tok.is(tok::annot_pragma_fenv_access) ||
  675. Tok.is(tok::annot_pragma_fenv_access_ms));
  676. tok::OnOffSwitch OOS =
  677. static_cast<tok::OnOffSwitch>(
  678. reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
  679. bool IsEnabled;
  680. switch (OOS) {
  681. case tok::OOS_ON:
  682. IsEnabled = true;
  683. break;
  684. case tok::OOS_OFF:
  685. IsEnabled = false;
  686. break;
  687. case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
  688. IsEnabled = false;
  689. break;
  690. }
  691. SourceLocation PragmaLoc = ConsumeAnnotationToken();
  692. Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
  693. }
  694. void Parser::HandlePragmaFEnvRound() {
  695. assert(Tok.is(tok::annot_pragma_fenv_round));
  696. auto RM = static_cast<llvm::RoundingMode>(
  697. reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
  698. SourceLocation PragmaLoc = ConsumeAnnotationToken();
  699. Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);
  700. }
  701. StmtResult Parser::HandlePragmaCaptured()
  702. {
  703. assert(Tok.is(tok::annot_pragma_captured));
  704. ConsumeAnnotationToken();
  705. if (Tok.isNot(tok::l_brace)) {
  706. PP.Diag(Tok, diag::err_expected) << tok::l_brace;
  707. return StmtError();
  708. }
  709. SourceLocation Loc = Tok.getLocation();
  710. ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
  711. Scope::CompoundStmtScope);
  712. Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
  713. /*NumParams=*/1);
  714. StmtResult R = ParseCompoundStatement();
  715. CapturedRegionScope.Exit();
  716. if (R.isInvalid()) {
  717. Actions.ActOnCapturedRegionError();
  718. return StmtError();
  719. }
  720. return Actions.ActOnCapturedRegionEnd(R.get());
  721. }
  722. namespace {
  723. enum OpenCLExtState : char {
  724. Disable, Enable, Begin, End
  725. };
  726. typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
  727. }
  728. void Parser::HandlePragmaOpenCLExtension() {
  729. assert(Tok.is(tok::annot_pragma_opencl_extension));
  730. OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
  731. auto State = Data->second;
  732. auto Ident = Data->first;
  733. SourceLocation NameLoc = Tok.getLocation();
  734. ConsumeAnnotationToken();
  735. auto &Opt = Actions.getOpenCLOptions();
  736. auto Name = Ident->getName();
  737. // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
  738. // overriding all previously issued extension directives, but only if the
  739. // behavior is set to disable."
  740. if (Name == "all") {
  741. if (State == Disable)
  742. Opt.disableAll();
  743. else
  744. PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
  745. } else if (State == Begin) {
  746. if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
  747. Opt.support(Name);
  748. // FIXME: Default behavior of the extension pragma is not defined.
  749. // Therefore, it should never be added by default.
  750. Opt.acceptsPragma(Name);
  751. }
  752. } else if (State == End) {
  753. // There is no behavior for this directive. We only accept this for
  754. // backward compatibility.
  755. } else if (!Opt.isKnown(Name) || !Opt.isWithPragma(Name))
  756. PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
  757. else if (Opt.isSupportedExtension(Name, getLangOpts()))
  758. Opt.enable(Name, State == Enable);
  759. else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts()))
  760. PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
  761. else
  762. PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
  763. }
  764. void Parser::HandlePragmaMSPointersToMembers() {
  765. assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
  766. LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
  767. static_cast<LangOptions::PragmaMSPointersToMembersKind>(
  768. reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
  769. SourceLocation PragmaLoc = ConsumeAnnotationToken();
  770. Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
  771. }
  772. void Parser::HandlePragmaMSVtorDisp() {
  773. assert(Tok.is(tok::annot_pragma_ms_vtordisp));
  774. uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
  775. Sema::PragmaMsStackAction Action =
  776. static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
  777. MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
  778. SourceLocation PragmaLoc = ConsumeAnnotationToken();
  779. Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
  780. }
  781. void Parser::HandlePragmaMSPragma() {
  782. assert(Tok.is(tok::annot_pragma_ms_pragma));
  783. // Grab the tokens out of the annotation and enter them into the stream.
  784. auto TheTokens =
  785. (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
  786. PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
  787. /*IsReinject=*/true);
  788. SourceLocation PragmaLocation = ConsumeAnnotationToken();
  789. assert(Tok.isAnyIdentifier());
  790. StringRef PragmaName = Tok.getIdentifierInfo()->getName();
  791. PP.Lex(Tok); // pragma kind
  792. // Figure out which #pragma we're dealing with. The switch has no default
  793. // because lex shouldn't emit the annotation token for unrecognized pragmas.
  794. typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
  795. PragmaHandler Handler =
  796. llvm::StringSwitch<PragmaHandler>(PragmaName)
  797. .Case("data_seg", &Parser::HandlePragmaMSSegment)
  798. .Case("bss_seg", &Parser::HandlePragmaMSSegment)
  799. .Case("const_seg", &Parser::HandlePragmaMSSegment)
  800. .Case("code_seg", &Parser::HandlePragmaMSSegment)
  801. .Case("section", &Parser::HandlePragmaMSSection)
  802. .Case("init_seg", &Parser::HandlePragmaMSInitSeg)
  803. .Case("strict_gs_check", &Parser::HandlePragmaMSStrictGuardStackCheck)
  804. .Case("function", &Parser::HandlePragmaMSFunction)
  805. .Case("alloc_text", &Parser::HandlePragmaMSAllocText)
  806. .Case("optimize", &Parser::HandlePragmaMSOptimize);
  807. if (!(this->*Handler)(PragmaName, PragmaLocation)) {
  808. // Pragma handling failed, and has been diagnosed. Slurp up the tokens
  809. // until eof (really end of line) to prevent follow-on errors.
  810. while (Tok.isNot(tok::eof))
  811. PP.Lex(Tok);
  812. PP.Lex(Tok);
  813. }
  814. }
  815. bool Parser::HandlePragmaMSSection(StringRef PragmaName,
  816. SourceLocation PragmaLocation) {
  817. if (Tok.isNot(tok::l_paren)) {
  818. PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
  819. return false;
  820. }
  821. PP.Lex(Tok); // (
  822. // Parsing code for pragma section
  823. if (Tok.isNot(tok::string_literal)) {
  824. PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
  825. << PragmaName;
  826. return false;
  827. }
  828. ExprResult StringResult = ParseStringLiteralExpression();
  829. if (StringResult.isInvalid())
  830. return false; // Already diagnosed.
  831. StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
  832. if (SegmentName->getCharByteWidth() != 1) {
  833. PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
  834. << PragmaName;
  835. return false;
  836. }
  837. int SectionFlags = ASTContext::PSF_Read;
  838. bool SectionFlagsAreDefault = true;
  839. while (Tok.is(tok::comma)) {
  840. PP.Lex(Tok); // ,
  841. // Ignore "long" and "short".
  842. // They are undocumented, but widely used, section attributes which appear
  843. // to do nothing.
  844. if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
  845. PP.Lex(Tok); // long/short
  846. continue;
  847. }
  848. if (!Tok.isAnyIdentifier()) {
  849. PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
  850. << PragmaName;
  851. return false;
  852. }
  853. ASTContext::PragmaSectionFlag Flag =
  854. llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
  855. Tok.getIdentifierInfo()->getName())
  856. .Case("read", ASTContext::PSF_Read)
  857. .Case("write", ASTContext::PSF_Write)
  858. .Case("execute", ASTContext::PSF_Execute)
  859. .Case("shared", ASTContext::PSF_Invalid)
  860. .Case("nopage", ASTContext::PSF_Invalid)
  861. .Case("nocache", ASTContext::PSF_Invalid)
  862. .Case("discard", ASTContext::PSF_Invalid)
  863. .Case("remove", ASTContext::PSF_Invalid)
  864. .Default(ASTContext::PSF_None);
  865. if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
  866. PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
  867. ? diag::warn_pragma_invalid_specific_action
  868. : diag::warn_pragma_unsupported_action)
  869. << PragmaName << Tok.getIdentifierInfo()->getName();
  870. return false;
  871. }
  872. SectionFlags |= Flag;
  873. SectionFlagsAreDefault = false;
  874. PP.Lex(Tok); // Identifier
  875. }
  876. // If no section attributes are specified, the section will be marked as
  877. // read/write.
  878. if (SectionFlagsAreDefault)
  879. SectionFlags |= ASTContext::PSF_Write;
  880. if (Tok.isNot(tok::r_paren)) {
  881. PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
  882. return false;
  883. }
  884. PP.Lex(Tok); // )
  885. if (Tok.isNot(tok::eof)) {
  886. PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
  887. << PragmaName;
  888. return false;
  889. }
  890. PP.Lex(Tok); // eof
  891. Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
  892. return true;
  893. }
  894. bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
  895. SourceLocation PragmaLocation) {
  896. if (Tok.isNot(tok::l_paren)) {
  897. PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
  898. return false;
  899. }
  900. PP.Lex(Tok); // (
  901. Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
  902. StringRef SlotLabel;
  903. if (Tok.isAnyIdentifier()) {
  904. StringRef PushPop = Tok.getIdentifierInfo()->getName();
  905. if (PushPop == "push")
  906. Action = Sema::PSK_Push;
  907. else if (PushPop == "pop")
  908. Action = Sema::PSK_Pop;
  909. else {
  910. PP.Diag(PragmaLocation,
  911. diag::warn_pragma_expected_section_push_pop_or_name)
  912. << PragmaName;
  913. return false;
  914. }
  915. if (Action != Sema::PSK_Reset) {
  916. PP.Lex(Tok); // push | pop
  917. if (Tok.is(tok::comma)) {
  918. PP.Lex(Tok); // ,
  919. // If we've got a comma, we either need a label or a string.
  920. if (Tok.isAnyIdentifier()) {
  921. SlotLabel = Tok.getIdentifierInfo()->getName();
  922. PP.Lex(Tok); // identifier
  923. if (Tok.is(tok::comma))
  924. PP.Lex(Tok);
  925. else if (Tok.isNot(tok::r_paren)) {
  926. PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
  927. << PragmaName;
  928. return false;
  929. }
  930. }
  931. } else if (Tok.isNot(tok::r_paren)) {
  932. PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
  933. return false;
  934. }
  935. }
  936. }
  937. // Grab the string literal for our section name.
  938. StringLiteral *SegmentName = nullptr;
  939. if (Tok.isNot(tok::r_paren)) {
  940. if (Tok.isNot(tok::string_literal)) {
  941. unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
  942. diag::warn_pragma_expected_section_name :
  943. diag::warn_pragma_expected_section_label_or_name :
  944. diag::warn_pragma_expected_section_push_pop_or_name;
  945. PP.Diag(PragmaLocation, DiagID) << PragmaName;
  946. return false;
  947. }
  948. ExprResult StringResult = ParseStringLiteralExpression();
  949. if (StringResult.isInvalid())
  950. return false; // Already diagnosed.
  951. SegmentName = cast<StringLiteral>(StringResult.get());
  952. if (SegmentName->getCharByteWidth() != 1) {
  953. PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
  954. << PragmaName;
  955. return false;
  956. }
  957. // Setting section "" has no effect
  958. if (SegmentName->getLength())
  959. Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
  960. }
  961. if (Tok.isNot(tok::r_paren)) {
  962. PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
  963. return false;
  964. }
  965. PP.Lex(Tok); // )
  966. if (Tok.isNot(tok::eof)) {
  967. PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
  968. << PragmaName;
  969. return false;
  970. }
  971. PP.Lex(Tok); // eof
  972. Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
  973. SegmentName, PragmaName);
  974. return true;
  975. }
  976. // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
  977. bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
  978. SourceLocation PragmaLocation) {
  979. if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
  980. PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
  981. return false;
  982. }
  983. if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
  984. PragmaName))
  985. return false;
  986. // Parse either the known section names or the string section name.
  987. StringLiteral *SegmentName = nullptr;
  988. if (Tok.isAnyIdentifier()) {
  989. auto *II = Tok.getIdentifierInfo();
  990. StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
  991. .Case("compiler", "\".CRT$XCC\"")
  992. .Case("lib", "\".CRT$XCL\"")
  993. .Case("user", "\".CRT$XCU\"")
  994. .Default("");
  995. if (!Section.empty()) {
  996. // Pretend the user wrote the appropriate string literal here.
  997. Token Toks[1];
  998. Toks[0].startToken();
  999. Toks[0].setKind(tok::string_literal);
  1000. Toks[0].setLocation(Tok.getLocation());
  1001. Toks[0].setLiteralData(Section.data());
  1002. Toks[0].setLength(Section.size());
  1003. SegmentName =
  1004. cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
  1005. PP.Lex(Tok);
  1006. }
  1007. } else if (Tok.is(tok::string_literal)) {
  1008. ExprResult StringResult = ParseStringLiteralExpression();
  1009. if (StringResult.isInvalid())
  1010. return false;
  1011. SegmentName = cast<StringLiteral>(StringResult.get());
  1012. if (SegmentName->getCharByteWidth() != 1) {
  1013. PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
  1014. << PragmaName;
  1015. return false;
  1016. }
  1017. // FIXME: Add support for the '[, func-name]' part of the pragma.
  1018. }
  1019. if (!SegmentName) {
  1020. PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
  1021. return false;
  1022. }
  1023. if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
  1024. PragmaName) ||
  1025. ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
  1026. PragmaName))
  1027. return false;
  1028. Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
  1029. return true;
  1030. }
  1031. // #pragma strict_gs_check(pop)
  1032. // #pragma strict_gs_check(push, "on" | "off")
  1033. // #pragma strict_gs_check("on" | "off")
  1034. bool Parser::HandlePragmaMSStrictGuardStackCheck(
  1035. StringRef PragmaName, SourceLocation PragmaLocation) {
  1036. if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
  1037. PragmaName))
  1038. return false;
  1039. Sema::PragmaMsStackAction Action = Sema::PSK_Set;
  1040. if (Tok.is(tok::identifier)) {
  1041. StringRef PushPop = Tok.getIdentifierInfo()->getName();
  1042. if (PushPop == "push") {
  1043. PP.Lex(Tok);
  1044. Action = Sema::PSK_Push;
  1045. if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_punc,
  1046. PragmaName))
  1047. return false;
  1048. } else if (PushPop == "pop") {
  1049. PP.Lex(Tok);
  1050. Action = Sema::PSK_Pop;
  1051. }
  1052. }
  1053. bool Value = false;
  1054. if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
  1055. const IdentifierInfo *II = Tok.getIdentifierInfo();
  1056. if (II && II->isStr("off")) {
  1057. PP.Lex(Tok);
  1058. Value = false;
  1059. } else if (II && II->isStr("on")) {
  1060. PP.Lex(Tok);
  1061. Value = true;
  1062. } else {
  1063. PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
  1064. << PragmaName;
  1065. return false;
  1066. }
  1067. }
  1068. // Finish the pragma: ')' $
  1069. if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
  1070. PragmaName))
  1071. return false;
  1072. if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
  1073. PragmaName))
  1074. return false;
  1075. Actions.ActOnPragmaMSStrictGuardStackCheck(PragmaLocation, Action, Value);
  1076. return true;
  1077. }
  1078. bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
  1079. SourceLocation PragmaLocation) {
  1080. Token FirstTok = Tok;
  1081. if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
  1082. PragmaName))
  1083. return false;
  1084. StringRef Section;
  1085. if (Tok.is(tok::string_literal)) {
  1086. ExprResult StringResult = ParseStringLiteralExpression();
  1087. if (StringResult.isInvalid())
  1088. return false; // Already diagnosed.
  1089. StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
  1090. if (SegmentName->getCharByteWidth() != 1) {
  1091. PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
  1092. << PragmaName;
  1093. return false;
  1094. }
  1095. Section = SegmentName->getString();
  1096. } else if (Tok.is(tok::identifier)) {
  1097. Section = Tok.getIdentifierInfo()->getName();
  1098. PP.Lex(Tok);
  1099. } else {
  1100. PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
  1101. << PragmaName;
  1102. return false;
  1103. }
  1104. if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
  1105. PragmaName))
  1106. return false;
  1107. SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> Functions;
  1108. while (true) {
  1109. if (Tok.isNot(tok::identifier)) {
  1110. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  1111. << PragmaName;
  1112. return false;
  1113. }
  1114. IdentifierInfo *II = Tok.getIdentifierInfo();
  1115. Functions.emplace_back(II, Tok.getLocation());
  1116. PP.Lex(Tok);
  1117. if (Tok.isNot(tok::comma))
  1118. break;
  1119. PP.Lex(Tok);
  1120. }
  1121. if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
  1122. PragmaName) ||
  1123. ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
  1124. PragmaName))
  1125. return false;
  1126. Actions.ActOnPragmaMSAllocText(FirstTok.getLocation(), Section, Functions);
  1127. return true;
  1128. }
  1129. static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
  1130. StringRef Str = PragmaName.getIdentifierInfo()->getName();
  1131. std::string ClangLoopStr("clang loop ");
  1132. if (Str == "loop" && Option.getIdentifierInfo())
  1133. ClangLoopStr += Option.getIdentifierInfo()->getName();
  1134. return std::string(llvm::StringSwitch<StringRef>(Str)
  1135. .Case("loop", ClangLoopStr)
  1136. .Case("unroll_and_jam", Str)
  1137. .Case("unroll", Str)
  1138. .Default(""));
  1139. }
  1140. bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
  1141. assert(Tok.is(tok::annot_pragma_loop_hint));
  1142. PragmaLoopHintInfo *Info =
  1143. static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
  1144. IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
  1145. Hint.PragmaNameLoc = IdentifierLoc::create(
  1146. Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
  1147. // It is possible that the loop hint has no option identifier, such as
  1148. // #pragma unroll(4).
  1149. IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
  1150. ? Info->Option.getIdentifierInfo()
  1151. : nullptr;
  1152. Hint.OptionLoc = IdentifierLoc::create(
  1153. Actions.Context, Info->Option.getLocation(), OptionInfo);
  1154. llvm::ArrayRef<Token> Toks = Info->Toks;
  1155. // Return a valid hint if pragma unroll or nounroll were specified
  1156. // without an argument.
  1157. auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
  1158. .Cases("unroll", "nounroll", "unroll_and_jam",
  1159. "nounroll_and_jam", true)
  1160. .Default(false);
  1161. if (Toks.empty() && IsLoopHint) {
  1162. ConsumeAnnotationToken();
  1163. Hint.Range = Info->PragmaName.getLocation();
  1164. return true;
  1165. }
  1166. // The constant expression is always followed by an eof token, which increases
  1167. // the TokSize by 1.
  1168. assert(!Toks.empty() &&
  1169. "PragmaLoopHintInfo::Toks must contain at least one token.");
  1170. // If no option is specified the argument is assumed to be a constant expr.
  1171. bool OptionUnroll = false;
  1172. bool OptionUnrollAndJam = false;
  1173. bool OptionDistribute = false;
  1174. bool OptionPipelineDisabled = false;
  1175. bool StateOption = false;
  1176. if (OptionInfo) { // Pragma Unroll does not specify an option.
  1177. OptionUnroll = OptionInfo->isStr("unroll");
  1178. OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
  1179. OptionDistribute = OptionInfo->isStr("distribute");
  1180. OptionPipelineDisabled = OptionInfo->isStr("pipeline");
  1181. StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
  1182. .Case("vectorize", true)
  1183. .Case("interleave", true)
  1184. .Case("vectorize_predicate", true)
  1185. .Default(false) ||
  1186. OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
  1187. OptionPipelineDisabled;
  1188. }
  1189. bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
  1190. !OptionDistribute && !OptionPipelineDisabled;
  1191. // Verify loop hint has an argument.
  1192. if (Toks[0].is(tok::eof)) {
  1193. ConsumeAnnotationToken();
  1194. Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
  1195. << /*StateArgument=*/StateOption
  1196. << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
  1197. << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
  1198. return false;
  1199. }
  1200. // Validate the argument.
  1201. if (StateOption) {
  1202. ConsumeAnnotationToken();
  1203. SourceLocation StateLoc = Toks[0].getLocation();
  1204. IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
  1205. bool Valid = StateInfo &&
  1206. llvm::StringSwitch<bool>(StateInfo->getName())
  1207. .Case("disable", true)
  1208. .Case("enable", !OptionPipelineDisabled)
  1209. .Case("full", OptionUnroll || OptionUnrollAndJam)
  1210. .Case("assume_safety", AssumeSafetyArg)
  1211. .Default(false);
  1212. if (!Valid) {
  1213. if (OptionPipelineDisabled) {
  1214. Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
  1215. } else {
  1216. Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
  1217. << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
  1218. << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
  1219. }
  1220. return false;
  1221. }
  1222. if (Toks.size() > 2)
  1223. Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1224. << PragmaLoopHintString(Info->PragmaName, Info->Option);
  1225. Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
  1226. } else if (OptionInfo && OptionInfo->getName() == "vectorize_width") {
  1227. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
  1228. /*IsReinject=*/false);
  1229. ConsumeAnnotationToken();
  1230. SourceLocation StateLoc = Toks[0].getLocation();
  1231. IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
  1232. StringRef IsScalableStr = StateInfo ? StateInfo->getName() : "";
  1233. // Look for vectorize_width(fixed|scalable)
  1234. if (IsScalableStr == "scalable" || IsScalableStr == "fixed") {
  1235. PP.Lex(Tok); // Identifier
  1236. if (Toks.size() > 2) {
  1237. Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1238. << PragmaLoopHintString(Info->PragmaName, Info->Option);
  1239. while (Tok.isNot(tok::eof))
  1240. ConsumeAnyToken();
  1241. }
  1242. Hint.StateLoc =
  1243. IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
  1244. ConsumeToken(); // Consume the constant expression eof terminator.
  1245. } else {
  1246. // Enter constant expression including eof terminator into token stream.
  1247. ExprResult R = ParseConstantExpression();
  1248. if (R.isInvalid() && !Tok.is(tok::comma))
  1249. Diag(Toks[0].getLocation(),
  1250. diag::note_pragma_loop_invalid_vectorize_option);
  1251. bool Arg2Error = false;
  1252. if (Tok.is(tok::comma)) {
  1253. PP.Lex(Tok); // ,
  1254. StateInfo = Tok.getIdentifierInfo();
  1255. IsScalableStr = StateInfo->getName();
  1256. if (IsScalableStr != "scalable" && IsScalableStr != "fixed") {
  1257. Diag(Tok.getLocation(),
  1258. diag::err_pragma_loop_invalid_vectorize_option);
  1259. Arg2Error = true;
  1260. } else
  1261. Hint.StateLoc =
  1262. IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
  1263. PP.Lex(Tok); // Identifier
  1264. }
  1265. // Tokens following an error in an ill-formed constant expression will
  1266. // remain in the token stream and must be removed.
  1267. if (Tok.isNot(tok::eof)) {
  1268. Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1269. << PragmaLoopHintString(Info->PragmaName, Info->Option);
  1270. while (Tok.isNot(tok::eof))
  1271. ConsumeAnyToken();
  1272. }
  1273. ConsumeToken(); // Consume the constant expression eof terminator.
  1274. if (Arg2Error || R.isInvalid() ||
  1275. Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
  1276. return false;
  1277. // Argument is a constant expression with an integer type.
  1278. Hint.ValueExpr = R.get();
  1279. }
  1280. } else {
  1281. // Enter constant expression including eof terminator into token stream.
  1282. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
  1283. /*IsReinject=*/false);
  1284. ConsumeAnnotationToken();
  1285. ExprResult R = ParseConstantExpression();
  1286. // Tokens following an error in an ill-formed constant expression will
  1287. // remain in the token stream and must be removed.
  1288. if (Tok.isNot(tok::eof)) {
  1289. Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1290. << PragmaLoopHintString(Info->PragmaName, Info->Option);
  1291. while (Tok.isNot(tok::eof))
  1292. ConsumeAnyToken();
  1293. }
  1294. ConsumeToken(); // Consume the constant expression eof terminator.
  1295. if (R.isInvalid() ||
  1296. Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
  1297. return false;
  1298. // Argument is a constant expression with an integer type.
  1299. Hint.ValueExpr = R.get();
  1300. }
  1301. Hint.Range = SourceRange(Info->PragmaName.getLocation(),
  1302. Info->Toks.back().getLocation());
  1303. return true;
  1304. }
  1305. namespace {
  1306. struct PragmaAttributeInfo {
  1307. enum ActionType { Push, Pop, Attribute };
  1308. ParsedAttributes &Attributes;
  1309. ActionType Action;
  1310. const IdentifierInfo *Namespace = nullptr;
  1311. ArrayRef<Token> Tokens;
  1312. PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
  1313. };
  1314. #include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
  1315. } // end anonymous namespace
  1316. static StringRef getIdentifier(const Token &Tok) {
  1317. if (Tok.is(tok::identifier))
  1318. return Tok.getIdentifierInfo()->getName();
  1319. const char *S = tok::getKeywordSpelling(Tok.getKind());
  1320. if (!S)
  1321. return "";
  1322. return S;
  1323. }
  1324. static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
  1325. using namespace attr;
  1326. switch (Rule) {
  1327. #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
  1328. case Value: \
  1329. return IsAbstract;
  1330. #include "clang/Basic/AttrSubMatchRulesList.inc"
  1331. }
  1332. llvm_unreachable("Invalid attribute subject match rule");
  1333. return false;
  1334. }
  1335. static void diagnoseExpectedAttributeSubjectSubRule(
  1336. Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
  1337. SourceLocation SubRuleLoc) {
  1338. auto Diagnostic =
  1339. PRef.Diag(SubRuleLoc,
  1340. diag::err_pragma_attribute_expected_subject_sub_identifier)
  1341. << PrimaryRuleName;
  1342. if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
  1343. Diagnostic << /*SubRulesSupported=*/1 << SubRules;
  1344. else
  1345. Diagnostic << /*SubRulesSupported=*/0;
  1346. }
  1347. static void diagnoseUnknownAttributeSubjectSubRule(
  1348. Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
  1349. StringRef SubRuleName, SourceLocation SubRuleLoc) {
  1350. auto Diagnostic =
  1351. PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
  1352. << SubRuleName << PrimaryRuleName;
  1353. if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
  1354. Diagnostic << /*SubRulesSupported=*/1 << SubRules;
  1355. else
  1356. Diagnostic << /*SubRulesSupported=*/0;
  1357. }
  1358. bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
  1359. attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
  1360. SourceLocation &LastMatchRuleEndLoc) {
  1361. bool IsAny = false;
  1362. BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
  1363. if (getIdentifier(Tok) == "any") {
  1364. AnyLoc = ConsumeToken();
  1365. IsAny = true;
  1366. if (AnyParens.expectAndConsume())
  1367. return true;
  1368. }
  1369. do {
  1370. // Parse the subject matcher rule.
  1371. StringRef Name = getIdentifier(Tok);
  1372. if (Name.empty()) {
  1373. Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
  1374. return true;
  1375. }
  1376. std::pair<std::optional<attr::SubjectMatchRule>,
  1377. std::optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
  1378. Rule = isAttributeSubjectMatchRule(Name);
  1379. if (!Rule.first) {
  1380. Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
  1381. return true;
  1382. }
  1383. attr::SubjectMatchRule PrimaryRule = *Rule.first;
  1384. SourceLocation RuleLoc = ConsumeToken();
  1385. BalancedDelimiterTracker Parens(*this, tok::l_paren);
  1386. if (isAbstractAttrMatcherRule(PrimaryRule)) {
  1387. if (Parens.expectAndConsume())
  1388. return true;
  1389. } else if (Parens.consumeOpen()) {
  1390. if (!SubjectMatchRules
  1391. .insert(
  1392. std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
  1393. .second)
  1394. Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
  1395. << Name
  1396. << FixItHint::CreateRemoval(SourceRange(
  1397. RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
  1398. LastMatchRuleEndLoc = RuleLoc;
  1399. continue;
  1400. }
  1401. // Parse the sub-rules.
  1402. StringRef SubRuleName = getIdentifier(Tok);
  1403. if (SubRuleName.empty()) {
  1404. diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
  1405. Tok.getLocation());
  1406. return true;
  1407. }
  1408. attr::SubjectMatchRule SubRule;
  1409. if (SubRuleName == "unless") {
  1410. SourceLocation SubRuleLoc = ConsumeToken();
  1411. BalancedDelimiterTracker Parens(*this, tok::l_paren);
  1412. if (Parens.expectAndConsume())
  1413. return true;
  1414. SubRuleName = getIdentifier(Tok);
  1415. if (SubRuleName.empty()) {
  1416. diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
  1417. SubRuleLoc);
  1418. return true;
  1419. }
  1420. auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
  1421. if (!SubRuleOrNone) {
  1422. std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
  1423. diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
  1424. SubRuleUnlessName, SubRuleLoc);
  1425. return true;
  1426. }
  1427. SubRule = *SubRuleOrNone;
  1428. ConsumeToken();
  1429. if (Parens.consumeClose())
  1430. return true;
  1431. } else {
  1432. auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
  1433. if (!SubRuleOrNone) {
  1434. diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
  1435. SubRuleName, Tok.getLocation());
  1436. return true;
  1437. }
  1438. SubRule = *SubRuleOrNone;
  1439. ConsumeToken();
  1440. }
  1441. SourceLocation RuleEndLoc = Tok.getLocation();
  1442. LastMatchRuleEndLoc = RuleEndLoc;
  1443. if (Parens.consumeClose())
  1444. return true;
  1445. if (!SubjectMatchRules
  1446. .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
  1447. .second) {
  1448. Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
  1449. << attr::getSubjectMatchRuleSpelling(SubRule)
  1450. << FixItHint::CreateRemoval(SourceRange(
  1451. RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
  1452. continue;
  1453. }
  1454. } while (IsAny && TryConsumeToken(tok::comma));
  1455. if (IsAny)
  1456. if (AnyParens.consumeClose())
  1457. return true;
  1458. return false;
  1459. }
  1460. namespace {
  1461. /// Describes the stage at which attribute subject rule parsing was interrupted.
  1462. enum class MissingAttributeSubjectRulesRecoveryPoint {
  1463. Comma,
  1464. ApplyTo,
  1465. Equals,
  1466. Any,
  1467. None,
  1468. };
  1469. MissingAttributeSubjectRulesRecoveryPoint
  1470. getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
  1471. if (const auto *II = Tok.getIdentifierInfo()) {
  1472. if (II->isStr("apply_to"))
  1473. return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
  1474. if (II->isStr("any"))
  1475. return MissingAttributeSubjectRulesRecoveryPoint::Any;
  1476. }
  1477. if (Tok.is(tok::equal))
  1478. return MissingAttributeSubjectRulesRecoveryPoint::Equals;
  1479. return MissingAttributeSubjectRulesRecoveryPoint::None;
  1480. }
  1481. /// Creates a diagnostic for the attribute subject rule parsing diagnostic that
  1482. /// suggests the possible attribute subject rules in a fix-it together with
  1483. /// any other missing tokens.
  1484. DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
  1485. unsigned DiagID, ParsedAttributes &Attrs,
  1486. MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
  1487. SourceLocation Loc = PRef.getEndOfPreviousToken();
  1488. if (Loc.isInvalid())
  1489. Loc = PRef.getCurToken().getLocation();
  1490. auto Diagnostic = PRef.Diag(Loc, DiagID);
  1491. std::string FixIt;
  1492. MissingAttributeSubjectRulesRecoveryPoint EndPoint =
  1493. getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
  1494. if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
  1495. FixIt = ", ";
  1496. if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
  1497. EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
  1498. FixIt += "apply_to";
  1499. if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
  1500. EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
  1501. FixIt += " = ";
  1502. SourceRange FixItRange(Loc);
  1503. if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
  1504. // Gather the subject match rules that are supported by the attribute.
  1505. // Add all the possible rules initially.
  1506. llvm::BitVector IsMatchRuleAvailable(attr::SubjectMatchRule_Last + 1, true);
  1507. // Remove the ones that are not supported by any of the attributes.
  1508. for (const ParsedAttr &Attribute : Attrs) {
  1509. SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> MatchRules;
  1510. Attribute.getMatchRules(PRef.getLangOpts(), MatchRules);
  1511. llvm::BitVector IsSupported(attr::SubjectMatchRule_Last + 1);
  1512. for (const auto &Rule : MatchRules) {
  1513. // Ensure that the missing rule is reported in the fix-it only when it's
  1514. // supported in the current language mode.
  1515. if (!Rule.second)
  1516. continue;
  1517. IsSupported[Rule.first] = true;
  1518. }
  1519. IsMatchRuleAvailable &= IsSupported;
  1520. }
  1521. if (IsMatchRuleAvailable.count() == 0) {
  1522. // FIXME: We can emit a "fix-it" with a subject list placeholder when
  1523. // placeholders will be supported by the fix-its.
  1524. return Diagnostic;
  1525. }
  1526. FixIt += "any(";
  1527. bool NeedsComma = false;
  1528. for (unsigned I = 0; I <= attr::SubjectMatchRule_Last; I++) {
  1529. if (!IsMatchRuleAvailable[I])
  1530. continue;
  1531. if (NeedsComma)
  1532. FixIt += ", ";
  1533. else
  1534. NeedsComma = true;
  1535. FixIt += attr::getSubjectMatchRuleSpelling(
  1536. static_cast<attr::SubjectMatchRule>(I));
  1537. }
  1538. FixIt += ")";
  1539. // Check if we need to remove the range
  1540. PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
  1541. FixItRange.setEnd(PRef.getCurToken().getLocation());
  1542. }
  1543. if (FixItRange.getBegin() == FixItRange.getEnd())
  1544. Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
  1545. else
  1546. Diagnostic << FixItHint::CreateReplacement(
  1547. CharSourceRange::getCharRange(FixItRange), FixIt);
  1548. return Diagnostic;
  1549. }
  1550. } // end anonymous namespace
  1551. void Parser::HandlePragmaAttribute() {
  1552. assert(Tok.is(tok::annot_pragma_attribute) &&
  1553. "Expected #pragma attribute annotation token");
  1554. SourceLocation PragmaLoc = Tok.getLocation();
  1555. auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
  1556. if (Info->Action == PragmaAttributeInfo::Pop) {
  1557. ConsumeAnnotationToken();
  1558. Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
  1559. return;
  1560. }
  1561. // Parse the actual attribute with its arguments.
  1562. assert((Info->Action == PragmaAttributeInfo::Push ||
  1563. Info->Action == PragmaAttributeInfo::Attribute) &&
  1564. "Unexpected #pragma attribute command");
  1565. if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
  1566. ConsumeAnnotationToken();
  1567. Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
  1568. return;
  1569. }
  1570. PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
  1571. /*IsReinject=*/false);
  1572. ConsumeAnnotationToken();
  1573. ParsedAttributes &Attrs = Info->Attributes;
  1574. Attrs.clearListOnly();
  1575. auto SkipToEnd = [this]() {
  1576. SkipUntil(tok::eof, StopBeforeMatch);
  1577. ConsumeToken();
  1578. };
  1579. if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
  1580. // Parse the CXX11 style attribute.
  1581. ParseCXX11AttributeSpecifier(Attrs);
  1582. } else if (Tok.is(tok::kw___attribute)) {
  1583. ConsumeToken();
  1584. if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
  1585. "attribute"))
  1586. return SkipToEnd();
  1587. if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
  1588. return SkipToEnd();
  1589. // FIXME: The practical usefulness of completion here is limited because
  1590. // we only get here if the line has balanced parens.
  1591. if (Tok.is(tok::code_completion)) {
  1592. cutOffParsing();
  1593. // FIXME: suppress completion of unsupported attributes?
  1594. Actions.CodeCompleteAttribute(AttributeCommonInfo::Syntax::AS_GNU);
  1595. return SkipToEnd();
  1596. }
  1597. // Parse the comma-separated list of attributes.
  1598. do {
  1599. if (Tok.isNot(tok::identifier)) {
  1600. Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
  1601. SkipToEnd();
  1602. return;
  1603. }
  1604. IdentifierInfo *AttrName = Tok.getIdentifierInfo();
  1605. SourceLocation AttrNameLoc = ConsumeToken();
  1606. if (Tok.isNot(tok::l_paren))
  1607. Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
  1608. ParsedAttr::AS_GNU);
  1609. else
  1610. ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
  1611. /*ScopeName=*/nullptr,
  1612. /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
  1613. /*Declarator=*/nullptr);
  1614. } while (TryConsumeToken(tok::comma));
  1615. if (ExpectAndConsume(tok::r_paren))
  1616. return SkipToEnd();
  1617. if (ExpectAndConsume(tok::r_paren))
  1618. return SkipToEnd();
  1619. } else if (Tok.is(tok::kw___declspec)) {
  1620. ParseMicrosoftDeclSpecs(Attrs);
  1621. } else {
  1622. Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
  1623. if (Tok.getIdentifierInfo()) {
  1624. // If we suspect that this is an attribute suggest the use of
  1625. // '__attribute__'.
  1626. if (ParsedAttr::getParsedKind(
  1627. Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
  1628. ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
  1629. SourceLocation InsertStartLoc = Tok.getLocation();
  1630. ConsumeToken();
  1631. if (Tok.is(tok::l_paren)) {
  1632. ConsumeAnyToken();
  1633. SkipUntil(tok::r_paren, StopBeforeMatch);
  1634. if (Tok.isNot(tok::r_paren))
  1635. return SkipToEnd();
  1636. }
  1637. Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
  1638. << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
  1639. << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
  1640. }
  1641. }
  1642. SkipToEnd();
  1643. return;
  1644. }
  1645. if (Attrs.empty() || Attrs.begin()->isInvalid()) {
  1646. SkipToEnd();
  1647. return;
  1648. }
  1649. for (const ParsedAttr &Attribute : Attrs) {
  1650. if (!Attribute.isSupportedByPragmaAttribute()) {
  1651. Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
  1652. << Attribute;
  1653. SkipToEnd();
  1654. return;
  1655. }
  1656. }
  1657. // Parse the subject-list.
  1658. if (!TryConsumeToken(tok::comma)) {
  1659. createExpectedAttributeSubjectRulesTokenDiagnostic(
  1660. diag::err_expected, Attrs,
  1661. MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
  1662. << tok::comma;
  1663. SkipToEnd();
  1664. return;
  1665. }
  1666. if (Tok.isNot(tok::identifier)) {
  1667. createExpectedAttributeSubjectRulesTokenDiagnostic(
  1668. diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
  1669. MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
  1670. SkipToEnd();
  1671. return;
  1672. }
  1673. const IdentifierInfo *II = Tok.getIdentifierInfo();
  1674. if (!II->isStr("apply_to")) {
  1675. createExpectedAttributeSubjectRulesTokenDiagnostic(
  1676. diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
  1677. MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
  1678. SkipToEnd();
  1679. return;
  1680. }
  1681. ConsumeToken();
  1682. if (!TryConsumeToken(tok::equal)) {
  1683. createExpectedAttributeSubjectRulesTokenDiagnostic(
  1684. diag::err_expected, Attrs,
  1685. MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
  1686. << tok::equal;
  1687. SkipToEnd();
  1688. return;
  1689. }
  1690. attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
  1691. SourceLocation AnyLoc, LastMatchRuleEndLoc;
  1692. if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
  1693. LastMatchRuleEndLoc)) {
  1694. SkipToEnd();
  1695. return;
  1696. }
  1697. // Tokens following an ill-formed attribute will remain in the token stream
  1698. // and must be removed.
  1699. if (Tok.isNot(tok::eof)) {
  1700. Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
  1701. SkipToEnd();
  1702. return;
  1703. }
  1704. // Consume the eof terminator token.
  1705. ConsumeToken();
  1706. // Handle a mixed push/attribute by desurging to a push, then an attribute.
  1707. if (Info->Action == PragmaAttributeInfo::Push)
  1708. Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
  1709. for (ParsedAttr &Attribute : Attrs) {
  1710. Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
  1711. SubjectMatchRules);
  1712. }
  1713. }
  1714. // #pragma GCC visibility comes in two variants:
  1715. // 'push' '(' [visibility] ')'
  1716. // 'pop'
  1717. void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
  1718. PragmaIntroducer Introducer,
  1719. Token &VisTok) {
  1720. SourceLocation VisLoc = VisTok.getLocation();
  1721. Token Tok;
  1722. PP.LexUnexpandedToken(Tok);
  1723. const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
  1724. const IdentifierInfo *VisType;
  1725. if (PushPop && PushPop->isStr("pop")) {
  1726. VisType = nullptr;
  1727. } else if (PushPop && PushPop->isStr("push")) {
  1728. PP.LexUnexpandedToken(Tok);
  1729. if (Tok.isNot(tok::l_paren)) {
  1730. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
  1731. << "visibility";
  1732. return;
  1733. }
  1734. PP.LexUnexpandedToken(Tok);
  1735. VisType = Tok.getIdentifierInfo();
  1736. if (!VisType) {
  1737. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  1738. << "visibility";
  1739. return;
  1740. }
  1741. PP.LexUnexpandedToken(Tok);
  1742. if (Tok.isNot(tok::r_paren)) {
  1743. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
  1744. << "visibility";
  1745. return;
  1746. }
  1747. } else {
  1748. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  1749. << "visibility";
  1750. return;
  1751. }
  1752. SourceLocation EndLoc = Tok.getLocation();
  1753. PP.LexUnexpandedToken(Tok);
  1754. if (Tok.isNot(tok::eod)) {
  1755. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1756. << "visibility";
  1757. return;
  1758. }
  1759. auto Toks = std::make_unique<Token[]>(1);
  1760. Toks[0].startToken();
  1761. Toks[0].setKind(tok::annot_pragma_vis);
  1762. Toks[0].setLocation(VisLoc);
  1763. Toks[0].setAnnotationEndLoc(EndLoc);
  1764. Toks[0].setAnnotationValue(
  1765. const_cast<void *>(static_cast<const void *>(VisType)));
  1766. PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
  1767. /*IsReinject=*/false);
  1768. }
  1769. // #pragma pack(...) comes in the following delicious flavors:
  1770. // pack '(' [integer] ')'
  1771. // pack '(' 'show' ')'
  1772. // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
  1773. void PragmaPackHandler::HandlePragma(Preprocessor &PP,
  1774. PragmaIntroducer Introducer,
  1775. Token &PackTok) {
  1776. SourceLocation PackLoc = PackTok.getLocation();
  1777. Token Tok;
  1778. PP.Lex(Tok);
  1779. if (Tok.isNot(tok::l_paren)) {
  1780. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
  1781. return;
  1782. }
  1783. Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
  1784. StringRef SlotLabel;
  1785. Token Alignment;
  1786. Alignment.startToken();
  1787. PP.Lex(Tok);
  1788. if (Tok.is(tok::numeric_constant)) {
  1789. Alignment = Tok;
  1790. PP.Lex(Tok);
  1791. // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
  1792. // the push/pop stack.
  1793. // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)
  1794. Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack)
  1795. ? Sema::PSK_Push_Set
  1796. : Sema::PSK_Set;
  1797. } else if (Tok.is(tok::identifier)) {
  1798. const IdentifierInfo *II = Tok.getIdentifierInfo();
  1799. if (II->isStr("show")) {
  1800. Action = Sema::PSK_Show;
  1801. PP.Lex(Tok);
  1802. } else {
  1803. if (II->isStr("push")) {
  1804. Action = Sema::PSK_Push;
  1805. } else if (II->isStr("pop")) {
  1806. Action = Sema::PSK_Pop;
  1807. } else {
  1808. PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
  1809. return;
  1810. }
  1811. PP.Lex(Tok);
  1812. if (Tok.is(tok::comma)) {
  1813. PP.Lex(Tok);
  1814. if (Tok.is(tok::numeric_constant)) {
  1815. Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
  1816. Alignment = Tok;
  1817. PP.Lex(Tok);
  1818. } else if (Tok.is(tok::identifier)) {
  1819. SlotLabel = Tok.getIdentifierInfo()->getName();
  1820. PP.Lex(Tok);
  1821. if (Tok.is(tok::comma)) {
  1822. PP.Lex(Tok);
  1823. if (Tok.isNot(tok::numeric_constant)) {
  1824. PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
  1825. return;
  1826. }
  1827. Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
  1828. Alignment = Tok;
  1829. PP.Lex(Tok);
  1830. }
  1831. } else {
  1832. PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
  1833. return;
  1834. }
  1835. }
  1836. }
  1837. } else if (PP.getLangOpts().ApplePragmaPack ||
  1838. PP.getLangOpts().XLPragmaPack) {
  1839. // In MSVC/gcc, #pragma pack() resets the alignment without affecting
  1840. // the push/pop stack.
  1841. // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma
  1842. // pack(pop).
  1843. Action = Sema::PSK_Pop;
  1844. }
  1845. if (Tok.isNot(tok::r_paren)) {
  1846. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
  1847. return;
  1848. }
  1849. SourceLocation RParenLoc = Tok.getLocation();
  1850. PP.Lex(Tok);
  1851. if (Tok.isNot(tok::eod)) {
  1852. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
  1853. return;
  1854. }
  1855. PragmaPackInfo *Info =
  1856. PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
  1857. Info->Action = Action;
  1858. Info->SlotLabel = SlotLabel;
  1859. Info->Alignment = Alignment;
  1860. MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
  1861. 1);
  1862. Toks[0].startToken();
  1863. Toks[0].setKind(tok::annot_pragma_pack);
  1864. Toks[0].setLocation(PackLoc);
  1865. Toks[0].setAnnotationEndLoc(RParenLoc);
  1866. Toks[0].setAnnotationValue(static_cast<void*>(Info));
  1867. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  1868. /*IsReinject=*/false);
  1869. }
  1870. // #pragma ms_struct on
  1871. // #pragma ms_struct off
  1872. void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
  1873. PragmaIntroducer Introducer,
  1874. Token &MSStructTok) {
  1875. PragmaMSStructKind Kind = PMSST_OFF;
  1876. Token Tok;
  1877. PP.Lex(Tok);
  1878. if (Tok.isNot(tok::identifier)) {
  1879. PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
  1880. return;
  1881. }
  1882. SourceLocation EndLoc = Tok.getLocation();
  1883. const IdentifierInfo *II = Tok.getIdentifierInfo();
  1884. if (II->isStr("on")) {
  1885. Kind = PMSST_ON;
  1886. PP.Lex(Tok);
  1887. }
  1888. else if (II->isStr("off") || II->isStr("reset"))
  1889. PP.Lex(Tok);
  1890. else {
  1891. PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
  1892. return;
  1893. }
  1894. if (Tok.isNot(tok::eod)) {
  1895. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1896. << "ms_struct";
  1897. return;
  1898. }
  1899. MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
  1900. 1);
  1901. Toks[0].startToken();
  1902. Toks[0].setKind(tok::annot_pragma_msstruct);
  1903. Toks[0].setLocation(MSStructTok.getLocation());
  1904. Toks[0].setAnnotationEndLoc(EndLoc);
  1905. Toks[0].setAnnotationValue(reinterpret_cast<void*>(
  1906. static_cast<uintptr_t>(Kind)));
  1907. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  1908. /*IsReinject=*/false);
  1909. }
  1910. // #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
  1911. void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
  1912. PragmaIntroducer Introducer,
  1913. Token &FirstToken) {
  1914. Token Tok;
  1915. auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
  1916. PP.Lex(Tok); // eat 'section'
  1917. while (Tok.isNot(tok::eod)) {
  1918. if (Tok.isNot(tok::identifier)) {
  1919. PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
  1920. return;
  1921. }
  1922. const IdentifierInfo *SecType = Tok.getIdentifierInfo();
  1923. if (SecType->isStr("bss"))
  1924. SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
  1925. else if (SecType->isStr("data"))
  1926. SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
  1927. else if (SecType->isStr("rodata"))
  1928. SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
  1929. else if (SecType->isStr("relro"))
  1930. SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;
  1931. else if (SecType->isStr("text"))
  1932. SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
  1933. else {
  1934. PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
  1935. return;
  1936. }
  1937. SourceLocation PragmaLocation = Tok.getLocation();
  1938. PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
  1939. if (Tok.isNot(tok::equal)) {
  1940. PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
  1941. return;
  1942. }
  1943. std::string SecName;
  1944. if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
  1945. return;
  1946. Actions.ActOnPragmaClangSection(
  1947. PragmaLocation,
  1948. (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set
  1949. : Sema::PragmaClangSectionAction::PCSA_Clear),
  1950. SecKind, SecName);
  1951. }
  1952. }
  1953. // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
  1954. // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
  1955. // #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
  1956. static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
  1957. bool IsOptions) {
  1958. Token Tok;
  1959. if (IsOptions) {
  1960. PP.Lex(Tok);
  1961. if (Tok.isNot(tok::identifier) ||
  1962. !Tok.getIdentifierInfo()->isStr("align")) {
  1963. PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
  1964. return;
  1965. }
  1966. }
  1967. PP.Lex(Tok);
  1968. if (PP.getLangOpts().XLPragmaPack) {
  1969. if (Tok.isNot(tok::l_paren)) {
  1970. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";
  1971. return;
  1972. }
  1973. } else if (Tok.isNot(tok::equal)) {
  1974. PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
  1975. << IsOptions;
  1976. return;
  1977. }
  1978. PP.Lex(Tok);
  1979. if (Tok.isNot(tok::identifier)) {
  1980. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  1981. << (IsOptions ? "options" : "align");
  1982. return;
  1983. }
  1984. Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
  1985. const IdentifierInfo *II = Tok.getIdentifierInfo();
  1986. if (II->isStr("native"))
  1987. Kind = Sema::POAK_Native;
  1988. else if (II->isStr("natural"))
  1989. Kind = Sema::POAK_Natural;
  1990. else if (II->isStr("packed"))
  1991. Kind = Sema::POAK_Packed;
  1992. else if (II->isStr("power"))
  1993. Kind = Sema::POAK_Power;
  1994. else if (II->isStr("mac68k"))
  1995. Kind = Sema::POAK_Mac68k;
  1996. else if (II->isStr("reset"))
  1997. Kind = Sema::POAK_Reset;
  1998. else {
  1999. PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
  2000. << IsOptions;
  2001. return;
  2002. }
  2003. if (PP.getLangOpts().XLPragmaPack) {
  2004. PP.Lex(Tok);
  2005. if (Tok.isNot(tok::r_paren)) {
  2006. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";
  2007. return;
  2008. }
  2009. }
  2010. SourceLocation EndLoc = Tok.getLocation();
  2011. PP.Lex(Tok);
  2012. if (Tok.isNot(tok::eod)) {
  2013. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  2014. << (IsOptions ? "options" : "align");
  2015. return;
  2016. }
  2017. MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
  2018. 1);
  2019. Toks[0].startToken();
  2020. Toks[0].setKind(tok::annot_pragma_align);
  2021. Toks[0].setLocation(FirstTok.getLocation());
  2022. Toks[0].setAnnotationEndLoc(EndLoc);
  2023. Toks[0].setAnnotationValue(reinterpret_cast<void*>(
  2024. static_cast<uintptr_t>(Kind)));
  2025. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  2026. /*IsReinject=*/false);
  2027. }
  2028. void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
  2029. PragmaIntroducer Introducer,
  2030. Token &AlignTok) {
  2031. ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
  2032. }
  2033. void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
  2034. PragmaIntroducer Introducer,
  2035. Token &OptionsTok) {
  2036. ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
  2037. }
  2038. // #pragma unused(identifier)
  2039. void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
  2040. PragmaIntroducer Introducer,
  2041. Token &UnusedTok) {
  2042. // FIXME: Should we be expanding macros here? My guess is no.
  2043. SourceLocation UnusedLoc = UnusedTok.getLocation();
  2044. // Lex the left '('.
  2045. Token Tok;
  2046. PP.Lex(Tok);
  2047. if (Tok.isNot(tok::l_paren)) {
  2048. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
  2049. return;
  2050. }
  2051. // Lex the declaration reference(s).
  2052. SmallVector<Token, 5> Identifiers;
  2053. SourceLocation RParenLoc;
  2054. bool LexID = true;
  2055. while (true) {
  2056. PP.Lex(Tok);
  2057. if (LexID) {
  2058. if (Tok.is(tok::identifier)) {
  2059. Identifiers.push_back(Tok);
  2060. LexID = false;
  2061. continue;
  2062. }
  2063. // Illegal token!
  2064. PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
  2065. return;
  2066. }
  2067. // We are execting a ')' or a ','.
  2068. if (Tok.is(tok::comma)) {
  2069. LexID = true;
  2070. continue;
  2071. }
  2072. if (Tok.is(tok::r_paren)) {
  2073. RParenLoc = Tok.getLocation();
  2074. break;
  2075. }
  2076. // Illegal token!
  2077. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
  2078. return;
  2079. }
  2080. PP.Lex(Tok);
  2081. if (Tok.isNot(tok::eod)) {
  2082. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
  2083. "unused";
  2084. return;
  2085. }
  2086. // Verify that we have a location for the right parenthesis.
  2087. assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
  2088. assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
  2089. // For each identifier token, insert into the token stream a
  2090. // annot_pragma_unused token followed by the identifier token.
  2091. // This allows us to cache a "#pragma unused" that occurs inside an inline
  2092. // C++ member function.
  2093. MutableArrayRef<Token> Toks(
  2094. PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
  2095. 2 * Identifiers.size());
  2096. for (unsigned i=0; i != Identifiers.size(); i++) {
  2097. Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
  2098. pragmaUnusedTok.startToken();
  2099. pragmaUnusedTok.setKind(tok::annot_pragma_unused);
  2100. pragmaUnusedTok.setLocation(UnusedLoc);
  2101. idTok = Identifiers[i];
  2102. }
  2103. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  2104. /*IsReinject=*/false);
  2105. }
  2106. // #pragma weak identifier
  2107. // #pragma weak identifier '=' identifier
  2108. void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
  2109. PragmaIntroducer Introducer,
  2110. Token &WeakTok) {
  2111. SourceLocation WeakLoc = WeakTok.getLocation();
  2112. Token Tok;
  2113. PP.Lex(Tok);
  2114. if (Tok.isNot(tok::identifier)) {
  2115. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
  2116. return;
  2117. }
  2118. Token WeakName = Tok;
  2119. bool HasAlias = false;
  2120. Token AliasName;
  2121. PP.Lex(Tok);
  2122. if (Tok.is(tok::equal)) {
  2123. HasAlias = true;
  2124. PP.Lex(Tok);
  2125. if (Tok.isNot(tok::identifier)) {
  2126. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  2127. << "weak";
  2128. return;
  2129. }
  2130. AliasName = Tok;
  2131. PP.Lex(Tok);
  2132. }
  2133. if (Tok.isNot(tok::eod)) {
  2134. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
  2135. return;
  2136. }
  2137. if (HasAlias) {
  2138. MutableArrayRef<Token> Toks(
  2139. PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
  2140. Token &pragmaUnusedTok = Toks[0];
  2141. pragmaUnusedTok.startToken();
  2142. pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
  2143. pragmaUnusedTok.setLocation(WeakLoc);
  2144. pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
  2145. Toks[1] = WeakName;
  2146. Toks[2] = AliasName;
  2147. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  2148. /*IsReinject=*/false);
  2149. } else {
  2150. MutableArrayRef<Token> Toks(
  2151. PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
  2152. Token &pragmaUnusedTok = Toks[0];
  2153. pragmaUnusedTok.startToken();
  2154. pragmaUnusedTok.setKind(tok::annot_pragma_weak);
  2155. pragmaUnusedTok.setLocation(WeakLoc);
  2156. pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
  2157. Toks[1] = WeakName;
  2158. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  2159. /*IsReinject=*/false);
  2160. }
  2161. }
  2162. // #pragma redefine_extname identifier identifier
  2163. void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
  2164. PragmaIntroducer Introducer,
  2165. Token &RedefToken) {
  2166. SourceLocation RedefLoc = RedefToken.getLocation();
  2167. Token Tok;
  2168. PP.Lex(Tok);
  2169. if (Tok.isNot(tok::identifier)) {
  2170. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
  2171. "redefine_extname";
  2172. return;
  2173. }
  2174. Token RedefName = Tok;
  2175. PP.Lex(Tok);
  2176. if (Tok.isNot(tok::identifier)) {
  2177. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  2178. << "redefine_extname";
  2179. return;
  2180. }
  2181. Token AliasName = Tok;
  2182. PP.Lex(Tok);
  2183. if (Tok.isNot(tok::eod)) {
  2184. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
  2185. "redefine_extname";
  2186. return;
  2187. }
  2188. MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
  2189. 3);
  2190. Token &pragmaRedefTok = Toks[0];
  2191. pragmaRedefTok.startToken();
  2192. pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
  2193. pragmaRedefTok.setLocation(RedefLoc);
  2194. pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
  2195. Toks[1] = RedefName;
  2196. Toks[2] = AliasName;
  2197. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  2198. /*IsReinject=*/false);
  2199. }
  2200. void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
  2201. PragmaIntroducer Introducer,
  2202. Token &Tok) {
  2203. tok::OnOffSwitch OOS;
  2204. if (PP.LexOnOffSwitch(OOS))
  2205. return;
  2206. MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
  2207. 1);
  2208. Toks[0].startToken();
  2209. Toks[0].setKind(tok::annot_pragma_fp_contract);
  2210. Toks[0].setLocation(Tok.getLocation());
  2211. Toks[0].setAnnotationEndLoc(Tok.getLocation());
  2212. Toks[0].setAnnotationValue(reinterpret_cast<void*>(
  2213. static_cast<uintptr_t>(OOS)));
  2214. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  2215. /*IsReinject=*/false);
  2216. }
  2217. void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
  2218. PragmaIntroducer Introducer,
  2219. Token &Tok) {
  2220. PP.LexUnexpandedToken(Tok);
  2221. if (Tok.isNot(tok::identifier)) {
  2222. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
  2223. "OPENCL";
  2224. return;
  2225. }
  2226. IdentifierInfo *Ext = Tok.getIdentifierInfo();
  2227. SourceLocation NameLoc = Tok.getLocation();
  2228. PP.Lex(Tok);
  2229. if (Tok.isNot(tok::colon)) {
  2230. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
  2231. return;
  2232. }
  2233. PP.Lex(Tok);
  2234. if (Tok.isNot(tok::identifier)) {
  2235. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
  2236. return;
  2237. }
  2238. IdentifierInfo *Pred = Tok.getIdentifierInfo();
  2239. OpenCLExtState State;
  2240. if (Pred->isStr("enable")) {
  2241. State = Enable;
  2242. } else if (Pred->isStr("disable")) {
  2243. State = Disable;
  2244. } else if (Pred->isStr("begin"))
  2245. State = Begin;
  2246. else if (Pred->isStr("end"))
  2247. State = End;
  2248. else {
  2249. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
  2250. << Ext->isStr("all");
  2251. return;
  2252. }
  2253. SourceLocation StateLoc = Tok.getLocation();
  2254. PP.Lex(Tok);
  2255. if (Tok.isNot(tok::eod)) {
  2256. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
  2257. "OPENCL EXTENSION";
  2258. return;
  2259. }
  2260. auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
  2261. Info->first = Ext;
  2262. Info->second = State;
  2263. MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
  2264. 1);
  2265. Toks[0].startToken();
  2266. Toks[0].setKind(tok::annot_pragma_opencl_extension);
  2267. Toks[0].setLocation(NameLoc);
  2268. Toks[0].setAnnotationValue(static_cast<void*>(Info));
  2269. Toks[0].setAnnotationEndLoc(StateLoc);
  2270. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  2271. /*IsReinject=*/false);
  2272. if (PP.getPPCallbacks())
  2273. PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
  2274. StateLoc, State);
  2275. }
  2276. /// Handle '#pragma omp ...' when OpenMP is disabled.
  2277. ///
  2278. void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
  2279. PragmaIntroducer Introducer,
  2280. Token &FirstTok) {
  2281. if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
  2282. FirstTok.getLocation())) {
  2283. PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
  2284. PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
  2285. diag::Severity::Ignored, SourceLocation());
  2286. }
  2287. PP.DiscardUntilEndOfDirective();
  2288. }
  2289. /// Handle '#pragma omp ...' when OpenMP is enabled.
  2290. ///
  2291. void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
  2292. PragmaIntroducer Introducer,
  2293. Token &FirstTok) {
  2294. SmallVector<Token, 16> Pragma;
  2295. Token Tok;
  2296. Tok.startToken();
  2297. Tok.setKind(tok::annot_pragma_openmp);
  2298. Tok.setLocation(Introducer.Loc);
  2299. while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
  2300. Pragma.push_back(Tok);
  2301. PP.Lex(Tok);
  2302. if (Tok.is(tok::annot_pragma_openmp)) {
  2303. PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
  2304. unsigned InnerPragmaCnt = 1;
  2305. while (InnerPragmaCnt != 0) {
  2306. PP.Lex(Tok);
  2307. if (Tok.is(tok::annot_pragma_openmp))
  2308. ++InnerPragmaCnt;
  2309. else if (Tok.is(tok::annot_pragma_openmp_end))
  2310. --InnerPragmaCnt;
  2311. }
  2312. PP.Lex(Tok);
  2313. }
  2314. }
  2315. SourceLocation EodLoc = Tok.getLocation();
  2316. Tok.startToken();
  2317. Tok.setKind(tok::annot_pragma_openmp_end);
  2318. Tok.setLocation(EodLoc);
  2319. Pragma.push_back(Tok);
  2320. auto Toks = std::make_unique<Token[]>(Pragma.size());
  2321. std::copy(Pragma.begin(), Pragma.end(), Toks.get());
  2322. PP.EnterTokenStream(std::move(Toks), Pragma.size(),
  2323. /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
  2324. }
  2325. /// Handle '#pragma pointers_to_members'
  2326. // The grammar for this pragma is as follows:
  2327. //
  2328. // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
  2329. //
  2330. // #pragma pointers_to_members '(' 'best_case' ')'
  2331. // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
  2332. // #pragma pointers_to_members '(' inheritance-model ')'
  2333. void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
  2334. PragmaIntroducer Introducer,
  2335. Token &Tok) {
  2336. SourceLocation PointersToMembersLoc = Tok.getLocation();
  2337. PP.Lex(Tok);
  2338. if (Tok.isNot(tok::l_paren)) {
  2339. PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
  2340. << "pointers_to_members";
  2341. return;
  2342. }
  2343. PP.Lex(Tok);
  2344. const IdentifierInfo *Arg = Tok.getIdentifierInfo();
  2345. if (!Arg) {
  2346. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  2347. << "pointers_to_members";
  2348. return;
  2349. }
  2350. PP.Lex(Tok);
  2351. LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
  2352. if (Arg->isStr("best_case")) {
  2353. RepresentationMethod = LangOptions::PPTMK_BestCase;
  2354. } else {
  2355. if (Arg->isStr("full_generality")) {
  2356. if (Tok.is(tok::comma)) {
  2357. PP.Lex(Tok);
  2358. Arg = Tok.getIdentifierInfo();
  2359. if (!Arg) {
  2360. PP.Diag(Tok.getLocation(),
  2361. diag::err_pragma_pointers_to_members_unknown_kind)
  2362. << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
  2363. return;
  2364. }
  2365. PP.Lex(Tok);
  2366. } else if (Tok.is(tok::r_paren)) {
  2367. // #pragma pointers_to_members(full_generality) implicitly specifies
  2368. // virtual_inheritance.
  2369. Arg = nullptr;
  2370. RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
  2371. } else {
  2372. PP.Diag(Tok.getLocation(), diag::err_expected_punc)
  2373. << "full_generality";
  2374. return;
  2375. }
  2376. }
  2377. if (Arg) {
  2378. if (Arg->isStr("single_inheritance")) {
  2379. RepresentationMethod =
  2380. LangOptions::PPTMK_FullGeneralitySingleInheritance;
  2381. } else if (Arg->isStr("multiple_inheritance")) {
  2382. RepresentationMethod =
  2383. LangOptions::PPTMK_FullGeneralityMultipleInheritance;
  2384. } else if (Arg->isStr("virtual_inheritance")) {
  2385. RepresentationMethod =
  2386. LangOptions::PPTMK_FullGeneralityVirtualInheritance;
  2387. } else {
  2388. PP.Diag(Tok.getLocation(),
  2389. diag::err_pragma_pointers_to_members_unknown_kind)
  2390. << Arg << /*HasPointerDeclaration*/ 1;
  2391. return;
  2392. }
  2393. }
  2394. }
  2395. if (Tok.isNot(tok::r_paren)) {
  2396. PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
  2397. << (Arg ? Arg->getName() : "full_generality");
  2398. return;
  2399. }
  2400. SourceLocation EndLoc = Tok.getLocation();
  2401. PP.Lex(Tok);
  2402. if (Tok.isNot(tok::eod)) {
  2403. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  2404. << "pointers_to_members";
  2405. return;
  2406. }
  2407. Token AnnotTok;
  2408. AnnotTok.startToken();
  2409. AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
  2410. AnnotTok.setLocation(PointersToMembersLoc);
  2411. AnnotTok.setAnnotationEndLoc(EndLoc);
  2412. AnnotTok.setAnnotationValue(
  2413. reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
  2414. PP.EnterToken(AnnotTok, /*IsReinject=*/true);
  2415. }
  2416. /// Handle '#pragma vtordisp'
  2417. // The grammar for this pragma is as follows:
  2418. //
  2419. // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
  2420. //
  2421. // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
  2422. // #pragma vtordisp '(' 'pop' ')'
  2423. // #pragma vtordisp '(' ')'
  2424. void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
  2425. PragmaIntroducer Introducer, Token &Tok) {
  2426. SourceLocation VtorDispLoc = Tok.getLocation();
  2427. PP.Lex(Tok);
  2428. if (Tok.isNot(tok::l_paren)) {
  2429. PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
  2430. return;
  2431. }
  2432. PP.Lex(Tok);
  2433. Sema::PragmaMsStackAction Action = Sema::PSK_Set;
  2434. const IdentifierInfo *II = Tok.getIdentifierInfo();
  2435. if (II) {
  2436. if (II->isStr("push")) {
  2437. // #pragma vtordisp(push, mode)
  2438. PP.Lex(Tok);
  2439. if (Tok.isNot(tok::comma)) {
  2440. PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
  2441. return;
  2442. }
  2443. PP.Lex(Tok);
  2444. Action = Sema::PSK_Push_Set;
  2445. // not push, could be on/off
  2446. } else if (II->isStr("pop")) {
  2447. // #pragma vtordisp(pop)
  2448. PP.Lex(Tok);
  2449. Action = Sema::PSK_Pop;
  2450. }
  2451. // not push or pop, could be on/off
  2452. } else {
  2453. if (Tok.is(tok::r_paren)) {
  2454. // #pragma vtordisp()
  2455. Action = Sema::PSK_Reset;
  2456. }
  2457. }
  2458. uint64_t Value = 0;
  2459. if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
  2460. const IdentifierInfo *II = Tok.getIdentifierInfo();
  2461. if (II && II->isStr("off")) {
  2462. PP.Lex(Tok);
  2463. Value = 0;
  2464. } else if (II && II->isStr("on")) {
  2465. PP.Lex(Tok);
  2466. Value = 1;
  2467. } else if (Tok.is(tok::numeric_constant) &&
  2468. PP.parseSimpleIntegerLiteral(Tok, Value)) {
  2469. if (Value > 2) {
  2470. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
  2471. << 0 << 2 << "vtordisp";
  2472. return;
  2473. }
  2474. } else {
  2475. PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
  2476. << "vtordisp";
  2477. return;
  2478. }
  2479. }
  2480. // Finish the pragma: ')' $
  2481. if (Tok.isNot(tok::r_paren)) {
  2482. PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
  2483. return;
  2484. }
  2485. SourceLocation EndLoc = Tok.getLocation();
  2486. PP.Lex(Tok);
  2487. if (Tok.isNot(tok::eod)) {
  2488. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  2489. << "vtordisp";
  2490. return;
  2491. }
  2492. // Enter the annotation.
  2493. Token AnnotTok;
  2494. AnnotTok.startToken();
  2495. AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
  2496. AnnotTok.setLocation(VtorDispLoc);
  2497. AnnotTok.setAnnotationEndLoc(EndLoc);
  2498. AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
  2499. static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
  2500. PP.EnterToken(AnnotTok, /*IsReinject=*/false);
  2501. }
  2502. /// Handle all MS pragmas. Simply forwards the tokens after inserting
  2503. /// an annotation token.
  2504. void PragmaMSPragma::HandlePragma(Preprocessor &PP,
  2505. PragmaIntroducer Introducer, Token &Tok) {
  2506. Token EoF, AnnotTok;
  2507. EoF.startToken();
  2508. EoF.setKind(tok::eof);
  2509. AnnotTok.startToken();
  2510. AnnotTok.setKind(tok::annot_pragma_ms_pragma);
  2511. AnnotTok.setLocation(Tok.getLocation());
  2512. AnnotTok.setAnnotationEndLoc(Tok.getLocation());
  2513. SmallVector<Token, 8> TokenVector;
  2514. // Suck up all of the tokens before the eod.
  2515. for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
  2516. TokenVector.push_back(Tok);
  2517. AnnotTok.setAnnotationEndLoc(Tok.getLocation());
  2518. }
  2519. // Add a sentinel EoF token to the end of the list.
  2520. TokenVector.push_back(EoF);
  2521. // We must allocate this array with new because EnterTokenStream is going to
  2522. // delete it later.
  2523. markAsReinjectedForRelexing(TokenVector);
  2524. auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
  2525. std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
  2526. auto Value = new (PP.getPreprocessorAllocator())
  2527. std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
  2528. TokenVector.size());
  2529. AnnotTok.setAnnotationValue(Value);
  2530. PP.EnterToken(AnnotTok, /*IsReinject*/ false);
  2531. }
  2532. /// Handle the \#pragma float_control extension.
  2533. ///
  2534. /// The syntax is:
  2535. /// \code
  2536. /// #pragma float_control(keyword[, setting] [,push])
  2537. /// \endcode
  2538. /// Where 'keyword' and 'setting' are identifiers.
  2539. // 'keyword' can be: precise, except, push, pop
  2540. // 'setting' can be: on, off
  2541. /// The optional arguments 'setting' and 'push' are supported only
  2542. /// when the keyword is 'precise' or 'except'.
  2543. void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
  2544. PragmaIntroducer Introducer,
  2545. Token &Tok) {
  2546. Sema::PragmaMsStackAction Action = Sema::PSK_Set;
  2547. SourceLocation FloatControlLoc = Tok.getLocation();
  2548. Token PragmaName = Tok;
  2549. if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
  2550. PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
  2551. << PragmaName.getIdentifierInfo()->getName();
  2552. return;
  2553. }
  2554. PP.Lex(Tok);
  2555. if (Tok.isNot(tok::l_paren)) {
  2556. PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
  2557. return;
  2558. }
  2559. // Read the identifier.
  2560. PP.Lex(Tok);
  2561. if (Tok.isNot(tok::identifier)) {
  2562. PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
  2563. return;
  2564. }
  2565. // Verify that this is one of the float control options.
  2566. IdentifierInfo *II = Tok.getIdentifierInfo();
  2567. PragmaFloatControlKind Kind =
  2568. llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
  2569. .Case("precise", PFC_Precise)
  2570. .Case("except", PFC_Except)
  2571. .Case("push", PFC_Push)
  2572. .Case("pop", PFC_Pop)
  2573. .Default(PFC_Unknown);
  2574. PP.Lex(Tok); // the identifier
  2575. if (Kind == PFC_Unknown) {
  2576. PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
  2577. return;
  2578. } else if (Kind == PFC_Push || Kind == PFC_Pop) {
  2579. if (Tok.isNot(tok::r_paren)) {
  2580. PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
  2581. return;
  2582. }
  2583. PP.Lex(Tok); // Eat the r_paren
  2584. Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;
  2585. } else {
  2586. if (Tok.is(tok::r_paren))
  2587. // Selecting Precise or Except
  2588. PP.Lex(Tok); // the r_paren
  2589. else if (Tok.isNot(tok::comma)) {
  2590. PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
  2591. return;
  2592. } else {
  2593. PP.Lex(Tok); // ,
  2594. if (!Tok.isAnyIdentifier()) {
  2595. PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
  2596. return;
  2597. }
  2598. StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
  2599. if (PushOnOff == "on")
  2600. // Kind is set correctly
  2601. ;
  2602. else if (PushOnOff == "off") {
  2603. if (Kind == PFC_Precise)
  2604. Kind = PFC_NoPrecise;
  2605. if (Kind == PFC_Except)
  2606. Kind = PFC_NoExcept;
  2607. } else if (PushOnOff == "push") {
  2608. Action = Sema::PSK_Push_Set;
  2609. } else {
  2610. PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
  2611. return;
  2612. }
  2613. PP.Lex(Tok); // the identifier
  2614. if (Tok.is(tok::comma)) {
  2615. PP.Lex(Tok); // ,
  2616. if (!Tok.isAnyIdentifier()) {
  2617. PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
  2618. return;
  2619. }
  2620. StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
  2621. if (ExpectedPush == "push") {
  2622. Action = Sema::PSK_Push_Set;
  2623. } else {
  2624. PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
  2625. return;
  2626. }
  2627. PP.Lex(Tok); // the push identifier
  2628. }
  2629. if (Tok.isNot(tok::r_paren)) {
  2630. PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
  2631. return;
  2632. }
  2633. PP.Lex(Tok); // the r_paren
  2634. }
  2635. }
  2636. SourceLocation EndLoc = Tok.getLocation();
  2637. if (Tok.isNot(tok::eod)) {
  2638. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  2639. << "float_control";
  2640. return;
  2641. }
  2642. // Note: there is no accomodation for PP callback for this pragma.
  2643. // Enter the annotation.
  2644. auto TokenArray = std::make_unique<Token[]>(1);
  2645. TokenArray[0].startToken();
  2646. TokenArray[0].setKind(tok::annot_pragma_float_control);
  2647. TokenArray[0].setLocation(FloatControlLoc);
  2648. TokenArray[0].setAnnotationEndLoc(EndLoc);
  2649. // Create an encoding of Action and Value by shifting the Action into
  2650. // the high 16 bits then union with the Kind.
  2651. TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
  2652. static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
  2653. PP.EnterTokenStream(std::move(TokenArray), 1,
  2654. /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
  2655. }
  2656. /// Handle the Microsoft \#pragma detect_mismatch extension.
  2657. ///
  2658. /// The syntax is:
  2659. /// \code
  2660. /// #pragma detect_mismatch("name", "value")
  2661. /// \endcode
  2662. /// Where 'name' and 'value' are quoted strings. The values are embedded in
  2663. /// the object file and passed along to the linker. If the linker detects a
  2664. /// mismatch in the object file's values for the given name, a LNK2038 error
  2665. /// is emitted. See MSDN for more details.
  2666. void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
  2667. PragmaIntroducer Introducer,
  2668. Token &Tok) {
  2669. SourceLocation DetectMismatchLoc = Tok.getLocation();
  2670. PP.Lex(Tok);
  2671. if (Tok.isNot(tok::l_paren)) {
  2672. PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
  2673. return;
  2674. }
  2675. // Read the name to embed, which must be a string literal.
  2676. std::string NameString;
  2677. if (!PP.LexStringLiteral(Tok, NameString,
  2678. "pragma detect_mismatch",
  2679. /*AllowMacroExpansion=*/true))
  2680. return;
  2681. // Read the comma followed by a second string literal.
  2682. std::string ValueString;
  2683. if (Tok.isNot(tok::comma)) {
  2684. PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
  2685. return;
  2686. }
  2687. if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
  2688. /*AllowMacroExpansion=*/true))
  2689. return;
  2690. if (Tok.isNot(tok::r_paren)) {
  2691. PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
  2692. return;
  2693. }
  2694. PP.Lex(Tok); // Eat the r_paren.
  2695. if (Tok.isNot(tok::eod)) {
  2696. PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
  2697. return;
  2698. }
  2699. // If the pragma is lexically sound, notify any interested PPCallbacks.
  2700. if (PP.getPPCallbacks())
  2701. PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
  2702. ValueString);
  2703. Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
  2704. }
  2705. /// Handle the microsoft \#pragma comment extension.
  2706. ///
  2707. /// The syntax is:
  2708. /// \code
  2709. /// #pragma comment(linker, "foo")
  2710. /// \endcode
  2711. /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
  2712. /// "foo" is a string, which is fully macro expanded, and permits string
  2713. /// concatenation, embedded escape characters etc. See MSDN for more details.
  2714. void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
  2715. PragmaIntroducer Introducer,
  2716. Token &Tok) {
  2717. SourceLocation CommentLoc = Tok.getLocation();
  2718. PP.Lex(Tok);
  2719. if (Tok.isNot(tok::l_paren)) {
  2720. PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
  2721. return;
  2722. }
  2723. // Read the identifier.
  2724. PP.Lex(Tok);
  2725. if (Tok.isNot(tok::identifier)) {
  2726. PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
  2727. return;
  2728. }
  2729. // Verify that this is one of the 5 explicitly listed options.
  2730. IdentifierInfo *II = Tok.getIdentifierInfo();
  2731. PragmaMSCommentKind Kind =
  2732. llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
  2733. .Case("linker", PCK_Linker)
  2734. .Case("lib", PCK_Lib)
  2735. .Case("compiler", PCK_Compiler)
  2736. .Case("exestr", PCK_ExeStr)
  2737. .Case("user", PCK_User)
  2738. .Default(PCK_Unknown);
  2739. if (Kind == PCK_Unknown) {
  2740. PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
  2741. return;
  2742. }
  2743. if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
  2744. PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
  2745. << II->getName();
  2746. return;
  2747. }
  2748. // Read the optional string if present.
  2749. PP.Lex(Tok);
  2750. std::string ArgumentString;
  2751. if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
  2752. "pragma comment",
  2753. /*AllowMacroExpansion=*/true))
  2754. return;
  2755. // FIXME: warn that 'exestr' is deprecated.
  2756. // FIXME: If the kind is "compiler" warn if the string is present (it is
  2757. // ignored).
  2758. // The MSDN docs say that "lib" and "linker" require a string and have a short
  2759. // list of linker options they support, but in practice MSVC doesn't
  2760. // issue a diagnostic. Therefore neither does clang.
  2761. if (Tok.isNot(tok::r_paren)) {
  2762. PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
  2763. return;
  2764. }
  2765. PP.Lex(Tok); // eat the r_paren.
  2766. if (Tok.isNot(tok::eod)) {
  2767. PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
  2768. return;
  2769. }
  2770. // If the pragma is lexically sound, notify any interested PPCallbacks.
  2771. if (PP.getPPCallbacks())
  2772. PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
  2773. Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
  2774. }
  2775. // #pragma clang optimize off
  2776. // #pragma clang optimize on
  2777. void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
  2778. PragmaIntroducer Introducer,
  2779. Token &FirstToken) {
  2780. Token Tok;
  2781. PP.Lex(Tok);
  2782. if (Tok.is(tok::eod)) {
  2783. PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
  2784. << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
  2785. return;
  2786. }
  2787. if (Tok.isNot(tok::identifier)) {
  2788. PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
  2789. << PP.getSpelling(Tok);
  2790. return;
  2791. }
  2792. const IdentifierInfo *II = Tok.getIdentifierInfo();
  2793. // The only accepted values are 'on' or 'off'.
  2794. bool IsOn = false;
  2795. if (II->isStr("on")) {
  2796. IsOn = true;
  2797. } else if (!II->isStr("off")) {
  2798. PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
  2799. << PP.getSpelling(Tok);
  2800. return;
  2801. }
  2802. PP.Lex(Tok);
  2803. if (Tok.isNot(tok::eod)) {
  2804. PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
  2805. << PP.getSpelling(Tok);
  2806. return;
  2807. }
  2808. Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
  2809. }
  2810. namespace {
  2811. /// Used as the annotation value for tok::annot_pragma_fp.
  2812. struct TokFPAnnotValue {
  2813. enum FlagKinds { Contract, Reassociate, Exceptions, EvalMethod };
  2814. enum FlagValues { On, Off, Fast };
  2815. std::optional<LangOptions::FPModeKind> ContractValue;
  2816. std::optional<LangOptions::FPModeKind> ReassociateValue;
  2817. std::optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
  2818. std::optional<LangOptions::FPEvalMethodKind> EvalMethodValue;
  2819. };
  2820. } // end anonymous namespace
  2821. void PragmaFPHandler::HandlePragma(Preprocessor &PP,
  2822. PragmaIntroducer Introducer, Token &Tok) {
  2823. // fp
  2824. Token PragmaName = Tok;
  2825. SmallVector<Token, 1> TokenList;
  2826. PP.Lex(Tok);
  2827. if (Tok.isNot(tok::identifier)) {
  2828. PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
  2829. << /*MissingOption=*/true << "";
  2830. return;
  2831. }
  2832. auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;
  2833. while (Tok.is(tok::identifier)) {
  2834. IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
  2835. auto FlagKind =
  2836. llvm::StringSwitch<std::optional<TokFPAnnotValue::FlagKinds>>(
  2837. OptionInfo->getName())
  2838. .Case("contract", TokFPAnnotValue::Contract)
  2839. .Case("reassociate", TokFPAnnotValue::Reassociate)
  2840. .Case("exceptions", TokFPAnnotValue::Exceptions)
  2841. .Case("eval_method", TokFPAnnotValue::EvalMethod)
  2842. .Default(std::nullopt);
  2843. if (!FlagKind) {
  2844. PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
  2845. << /*MissingOption=*/false << OptionInfo;
  2846. return;
  2847. }
  2848. PP.Lex(Tok);
  2849. // Read '('
  2850. if (Tok.isNot(tok::l_paren)) {
  2851. PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
  2852. return;
  2853. }
  2854. PP.Lex(Tok);
  2855. bool isEvalMethodDouble =
  2856. Tok.is(tok::kw_double) && FlagKind == TokFPAnnotValue::EvalMethod;
  2857. // Don't diagnose if we have an eval_metod pragma with "double" kind.
  2858. if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) {
  2859. PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
  2860. << PP.getSpelling(Tok) << OptionInfo->getName()
  2861. << static_cast<int>(*FlagKind);
  2862. return;
  2863. }
  2864. const IdentifierInfo *II = Tok.getIdentifierInfo();
  2865. if (FlagKind == TokFPAnnotValue::Contract) {
  2866. AnnotValue->ContractValue =
  2867. llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
  2868. II->getName())
  2869. .Case("on", LangOptions::FPModeKind::FPM_On)
  2870. .Case("off", LangOptions::FPModeKind::FPM_Off)
  2871. .Case("fast", LangOptions::FPModeKind::FPM_Fast)
  2872. .Default(std::nullopt);
  2873. if (!AnnotValue->ContractValue) {
  2874. PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
  2875. << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
  2876. return;
  2877. }
  2878. } else if (FlagKind == TokFPAnnotValue::Reassociate) {
  2879. AnnotValue->ReassociateValue =
  2880. llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
  2881. II->getName())
  2882. .Case("on", LangOptions::FPModeKind::FPM_On)
  2883. .Case("off", LangOptions::FPModeKind::FPM_Off)
  2884. .Default(std::nullopt);
  2885. if (!AnnotValue->ReassociateValue) {
  2886. PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
  2887. << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
  2888. return;
  2889. }
  2890. } else if (FlagKind == TokFPAnnotValue::Exceptions) {
  2891. AnnotValue->ExceptionsValue =
  2892. llvm::StringSwitch<std::optional<LangOptions::FPExceptionModeKind>>(
  2893. II->getName())
  2894. .Case("ignore", LangOptions::FPE_Ignore)
  2895. .Case("maytrap", LangOptions::FPE_MayTrap)
  2896. .Case("strict", LangOptions::FPE_Strict)
  2897. .Default(std::nullopt);
  2898. if (!AnnotValue->ExceptionsValue) {
  2899. PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
  2900. << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
  2901. return;
  2902. }
  2903. } else if (FlagKind == TokFPAnnotValue::EvalMethod) {
  2904. AnnotValue->EvalMethodValue =
  2905. llvm::StringSwitch<std::optional<LangOptions::FPEvalMethodKind>>(
  2906. II->getName())
  2907. .Case("source", LangOptions::FPEvalMethodKind::FEM_Source)
  2908. .Case("double", LangOptions::FPEvalMethodKind::FEM_Double)
  2909. .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended)
  2910. .Default(std::nullopt);
  2911. if (!AnnotValue->EvalMethodValue) {
  2912. PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
  2913. << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
  2914. return;
  2915. }
  2916. }
  2917. PP.Lex(Tok);
  2918. // Read ')'
  2919. if (Tok.isNot(tok::r_paren)) {
  2920. PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
  2921. return;
  2922. }
  2923. PP.Lex(Tok);
  2924. }
  2925. if (Tok.isNot(tok::eod)) {
  2926. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  2927. << "clang fp";
  2928. return;
  2929. }
  2930. Token FPTok;
  2931. FPTok.startToken();
  2932. FPTok.setKind(tok::annot_pragma_fp);
  2933. FPTok.setLocation(PragmaName.getLocation());
  2934. FPTok.setAnnotationEndLoc(PragmaName.getLocation());
  2935. FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
  2936. TokenList.push_back(FPTok);
  2937. auto TokenArray = std::make_unique<Token[]>(TokenList.size());
  2938. std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
  2939. PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
  2940. /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
  2941. }
  2942. void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
  2943. PragmaIntroducer Introducer,
  2944. Token &Tok) {
  2945. Token PragmaName = Tok;
  2946. SmallVector<Token, 1> TokenList;
  2947. if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
  2948. PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
  2949. << PragmaName.getIdentifierInfo()->getName();
  2950. return;
  2951. }
  2952. PP.Lex(Tok);
  2953. if (Tok.isNot(tok::identifier)) {
  2954. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  2955. << PragmaName.getIdentifierInfo()->getName();
  2956. return;
  2957. }
  2958. IdentifierInfo *II = Tok.getIdentifierInfo();
  2959. auto RM =
  2960. llvm::StringSwitch<llvm::RoundingMode>(II->getName())
  2961. .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)
  2962. .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)
  2963. .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)
  2964. .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)
  2965. .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)
  2966. .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)
  2967. .Default(llvm::RoundingMode::Invalid);
  2968. if (RM == llvm::RoundingMode::Invalid) {
  2969. PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);
  2970. return;
  2971. }
  2972. PP.Lex(Tok);
  2973. if (Tok.isNot(tok::eod)) {
  2974. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  2975. << "STDC FENV_ROUND";
  2976. return;
  2977. }
  2978. // Until the pragma is fully implemented, issue a warning.
  2979. PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
  2980. MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
  2981. 1);
  2982. Toks[0].startToken();
  2983. Toks[0].setKind(tok::annot_pragma_fenv_round);
  2984. Toks[0].setLocation(Tok.getLocation());
  2985. Toks[0].setAnnotationEndLoc(Tok.getLocation());
  2986. Toks[0].setAnnotationValue(
  2987. reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));
  2988. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
  2989. /*IsReinject=*/false);
  2990. }
  2991. void Parser::HandlePragmaFP() {
  2992. assert(Tok.is(tok::annot_pragma_fp));
  2993. auto *AnnotValue =
  2994. reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
  2995. if (AnnotValue->ReassociateValue)
  2996. Actions.ActOnPragmaFPReassociate(Tok.getLocation(),
  2997. *AnnotValue->ReassociateValue ==
  2998. LangOptions::FPModeKind::FPM_On);
  2999. if (AnnotValue->ContractValue)
  3000. Actions.ActOnPragmaFPContract(Tok.getLocation(),
  3001. *AnnotValue->ContractValue);
  3002. if (AnnotValue->ExceptionsValue)
  3003. Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
  3004. *AnnotValue->ExceptionsValue);
  3005. if (AnnotValue->EvalMethodValue)
  3006. Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(),
  3007. *AnnotValue->EvalMethodValue);
  3008. ConsumeAnnotationToken();
  3009. }
  3010. /// Parses loop or unroll pragma hint value and fills in Info.
  3011. static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
  3012. Token Option, bool ValueInParens,
  3013. PragmaLoopHintInfo &Info) {
  3014. SmallVector<Token, 1> ValueList;
  3015. int OpenParens = ValueInParens ? 1 : 0;
  3016. // Read constant expression.
  3017. while (Tok.isNot(tok::eod)) {
  3018. if (Tok.is(tok::l_paren))
  3019. OpenParens++;
  3020. else if (Tok.is(tok::r_paren)) {
  3021. OpenParens--;
  3022. if (OpenParens == 0 && ValueInParens)
  3023. break;
  3024. }
  3025. ValueList.push_back(Tok);
  3026. PP.Lex(Tok);
  3027. }
  3028. if (ValueInParens) {
  3029. // Read ')'
  3030. if (Tok.isNot(tok::r_paren)) {
  3031. PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
  3032. return true;
  3033. }
  3034. PP.Lex(Tok);
  3035. }
  3036. Token EOFTok;
  3037. EOFTok.startToken();
  3038. EOFTok.setKind(tok::eof);
  3039. EOFTok.setLocation(Tok.getLocation());
  3040. ValueList.push_back(EOFTok); // Terminates expression for parsing.
  3041. markAsReinjectedForRelexing(ValueList);
  3042. Info.Toks = llvm::ArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
  3043. Info.PragmaName = PragmaName;
  3044. Info.Option = Option;
  3045. return false;
  3046. }
  3047. /// Handle the \#pragma clang loop directive.
  3048. /// #pragma clang 'loop' loop-hints
  3049. ///
  3050. /// loop-hints:
  3051. /// loop-hint loop-hints[opt]
  3052. ///
  3053. /// loop-hint:
  3054. /// 'vectorize' '(' loop-hint-keyword ')'
  3055. /// 'interleave' '(' loop-hint-keyword ')'
  3056. /// 'unroll' '(' unroll-hint-keyword ')'
  3057. /// 'vectorize_predicate' '(' loop-hint-keyword ')'
  3058. /// 'vectorize_width' '(' loop-hint-value ')'
  3059. /// 'interleave_count' '(' loop-hint-value ')'
  3060. /// 'unroll_count' '(' loop-hint-value ')'
  3061. /// 'pipeline' '(' disable ')'
  3062. /// 'pipeline_initiation_interval' '(' loop-hint-value ')'
  3063. ///
  3064. /// loop-hint-keyword:
  3065. /// 'enable'
  3066. /// 'disable'
  3067. /// 'assume_safety'
  3068. ///
  3069. /// unroll-hint-keyword:
  3070. /// 'enable'
  3071. /// 'disable'
  3072. /// 'full'
  3073. ///
  3074. /// loop-hint-value:
  3075. /// constant-expression
  3076. ///
  3077. /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
  3078. /// try vectorizing the instructions of the loop it precedes. Specifying
  3079. /// interleave(enable) or interleave_count(_value_) instructs llvm to try
  3080. /// interleaving multiple iterations of the loop it precedes. The width of the
  3081. /// vector instructions is specified by vectorize_width() and the number of
  3082. /// interleaved loop iterations is specified by interleave_count(). Specifying a
  3083. /// value of 1 effectively disables vectorization/interleaving, even if it is
  3084. /// possible and profitable, and 0 is invalid. The loop vectorizer currently
  3085. /// only works on inner loops.
  3086. ///
  3087. /// The unroll and unroll_count directives control the concatenation
  3088. /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
  3089. /// completely if the trip count is known at compile time and unroll partially
  3090. /// if the trip count is not known. Specifying unroll(full) is similar to
  3091. /// unroll(enable) but will unroll the loop only if the trip count is known at
  3092. /// compile time. Specifying unroll(disable) disables unrolling for the
  3093. /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
  3094. /// loop the number of times indicated by the value.
  3095. void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
  3096. PragmaIntroducer Introducer,
  3097. Token &Tok) {
  3098. // Incoming token is "loop" from "#pragma clang loop".
  3099. Token PragmaName = Tok;
  3100. SmallVector<Token, 1> TokenList;
  3101. // Lex the optimization option and verify it is an identifier.
  3102. PP.Lex(Tok);
  3103. if (Tok.isNot(tok::identifier)) {
  3104. PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
  3105. << /*MissingOption=*/true << "";
  3106. return;
  3107. }
  3108. while (Tok.is(tok::identifier)) {
  3109. Token Option = Tok;
  3110. IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
  3111. bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
  3112. .Case("vectorize", true)
  3113. .Case("interleave", true)
  3114. .Case("unroll", true)
  3115. .Case("distribute", true)
  3116. .Case("vectorize_predicate", true)
  3117. .Case("vectorize_width", true)
  3118. .Case("interleave_count", true)
  3119. .Case("unroll_count", true)
  3120. .Case("pipeline", true)
  3121. .Case("pipeline_initiation_interval", true)
  3122. .Default(false);
  3123. if (!OptionValid) {
  3124. PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
  3125. << /*MissingOption=*/false << OptionInfo;
  3126. return;
  3127. }
  3128. PP.Lex(Tok);
  3129. // Read '('
  3130. if (Tok.isNot(tok::l_paren)) {
  3131. PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
  3132. return;
  3133. }
  3134. PP.Lex(Tok);
  3135. auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
  3136. if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
  3137. *Info))
  3138. return;
  3139. // Generate the loop hint token.
  3140. Token LoopHintTok;
  3141. LoopHintTok.startToken();
  3142. LoopHintTok.setKind(tok::annot_pragma_loop_hint);
  3143. LoopHintTok.setLocation(Introducer.Loc);
  3144. LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
  3145. LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
  3146. TokenList.push_back(LoopHintTok);
  3147. }
  3148. if (Tok.isNot(tok::eod)) {
  3149. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  3150. << "clang loop";
  3151. return;
  3152. }
  3153. auto TokenArray = std::make_unique<Token[]>(TokenList.size());
  3154. std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
  3155. PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
  3156. /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
  3157. }
  3158. /// Handle the loop unroll optimization pragmas.
  3159. /// #pragma unroll
  3160. /// #pragma unroll unroll-hint-value
  3161. /// #pragma unroll '(' unroll-hint-value ')'
  3162. /// #pragma nounroll
  3163. /// #pragma unroll_and_jam
  3164. /// #pragma unroll_and_jam unroll-hint-value
  3165. /// #pragma unroll_and_jam '(' unroll-hint-value ')'
  3166. /// #pragma nounroll_and_jam
  3167. ///
  3168. /// unroll-hint-value:
  3169. /// constant-expression
  3170. ///
  3171. /// Loop unrolling hints can be specified with '#pragma unroll' or
  3172. /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
  3173. /// contained in parentheses. With no argument the directive instructs llvm to
  3174. /// try to unroll the loop completely. A positive integer argument can be
  3175. /// specified to indicate the number of times the loop should be unrolled. To
  3176. /// maximize compatibility with other compilers the unroll count argument can be
  3177. /// specified with or without parentheses. Specifying, '#pragma nounroll'
  3178. /// disables unrolling of the loop.
  3179. void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
  3180. PragmaIntroducer Introducer,
  3181. Token &Tok) {
  3182. // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
  3183. // "#pragma nounroll".
  3184. Token PragmaName = Tok;
  3185. PP.Lex(Tok);
  3186. auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
  3187. if (Tok.is(tok::eod)) {
  3188. // nounroll or unroll pragma without an argument.
  3189. Info->PragmaName = PragmaName;
  3190. Info->Option.startToken();
  3191. } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
  3192. PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
  3193. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  3194. << PragmaName.getIdentifierInfo()->getName();
  3195. return;
  3196. } else {
  3197. // Unroll pragma with an argument: "#pragma unroll N" or
  3198. // "#pragma unroll(N)".
  3199. // Read '(' if it exists.
  3200. bool ValueInParens = Tok.is(tok::l_paren);
  3201. if (ValueInParens)
  3202. PP.Lex(Tok);
  3203. Token Option;
  3204. Option.startToken();
  3205. if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
  3206. return;
  3207. // In CUDA, the argument to '#pragma unroll' should not be contained in
  3208. // parentheses.
  3209. if (PP.getLangOpts().CUDA && ValueInParens)
  3210. PP.Diag(Info->Toks[0].getLocation(),
  3211. diag::warn_pragma_unroll_cuda_value_in_parens);
  3212. if (Tok.isNot(tok::eod)) {
  3213. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  3214. << "unroll";
  3215. return;
  3216. }
  3217. }
  3218. // Generate the hint token.
  3219. auto TokenArray = std::make_unique<Token[]>(1);
  3220. TokenArray[0].startToken();
  3221. TokenArray[0].setKind(tok::annot_pragma_loop_hint);
  3222. TokenArray[0].setLocation(Introducer.Loc);
  3223. TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
  3224. TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
  3225. PP.EnterTokenStream(std::move(TokenArray), 1,
  3226. /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
  3227. }
  3228. /// Handle the Microsoft \#pragma intrinsic extension.
  3229. ///
  3230. /// The syntax is:
  3231. /// \code
  3232. /// #pragma intrinsic(memset)
  3233. /// #pragma intrinsic(strlen, memcpy)
  3234. /// \endcode
  3235. ///
  3236. /// Pragma intrisic tells the compiler to use a builtin version of the
  3237. /// function. Clang does it anyway, so the pragma doesn't really do anything.
  3238. /// Anyway, we emit a warning if the function specified in \#pragma intrinsic
  3239. /// isn't an intrinsic in clang and suggest to include intrin.h.
  3240. void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
  3241. PragmaIntroducer Introducer,
  3242. Token &Tok) {
  3243. PP.Lex(Tok);
  3244. if (Tok.isNot(tok::l_paren)) {
  3245. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
  3246. << "intrinsic";
  3247. return;
  3248. }
  3249. PP.Lex(Tok);
  3250. bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
  3251. while (Tok.is(tok::identifier)) {
  3252. IdentifierInfo *II = Tok.getIdentifierInfo();
  3253. if (!II->getBuiltinID())
  3254. PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
  3255. << II << SuggestIntrinH;
  3256. PP.Lex(Tok);
  3257. if (Tok.isNot(tok::comma))
  3258. break;
  3259. PP.Lex(Tok);
  3260. }
  3261. if (Tok.isNot(tok::r_paren)) {
  3262. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
  3263. << "intrinsic";
  3264. return;
  3265. }
  3266. PP.Lex(Tok);
  3267. if (Tok.isNot(tok::eod))
  3268. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  3269. << "intrinsic";
  3270. }
  3271. bool Parser::HandlePragmaMSFunction(StringRef PragmaName,
  3272. SourceLocation PragmaLocation) {
  3273. Token FirstTok = Tok;
  3274. if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
  3275. PragmaName))
  3276. return false;
  3277. bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
  3278. llvm::SmallVector<StringRef> NoBuiltins;
  3279. while (Tok.is(tok::identifier)) {
  3280. IdentifierInfo *II = Tok.getIdentifierInfo();
  3281. if (!II->getBuiltinID())
  3282. PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
  3283. << II << SuggestIntrinH;
  3284. else
  3285. NoBuiltins.emplace_back(II->getName());
  3286. PP.Lex(Tok);
  3287. if (Tok.isNot(tok::comma))
  3288. break;
  3289. PP.Lex(Tok); // ,
  3290. }
  3291. if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
  3292. PragmaName) ||
  3293. ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
  3294. PragmaName))
  3295. return false;
  3296. Actions.ActOnPragmaMSFunction(FirstTok.getLocation(), NoBuiltins);
  3297. return true;
  3298. }
  3299. // #pragma optimize("gsty", on|off)
  3300. bool Parser::HandlePragmaMSOptimize(StringRef PragmaName,
  3301. SourceLocation PragmaLocation) {
  3302. Token FirstTok = Tok;
  3303. if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
  3304. PragmaName))
  3305. return false;
  3306. if (Tok.isNot(tok::string_literal)) {
  3307. PP.Diag(PragmaLocation, diag::warn_pragma_expected_string) << PragmaName;
  3308. return false;
  3309. }
  3310. ExprResult StringResult = ParseStringLiteralExpression();
  3311. if (StringResult.isInvalid())
  3312. return false; // Already diagnosed.
  3313. StringLiteral *OptimizationList = cast<StringLiteral>(StringResult.get());
  3314. if (OptimizationList->getCharByteWidth() != 1) {
  3315. PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
  3316. << PragmaName;
  3317. return false;
  3318. }
  3319. if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
  3320. PragmaName))
  3321. return false;
  3322. if (Tok.is(tok::eof) || Tok.is(tok::r_paren)) {
  3323. PP.Diag(PragmaLocation, diag::warn_pragma_missing_argument)
  3324. << PragmaName << /*Expected=*/true << "'on' or 'off'";
  3325. return false;
  3326. }
  3327. IdentifierInfo *II = Tok.getIdentifierInfo();
  3328. if (!II || (!II->isStr("on") && !II->isStr("off"))) {
  3329. PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
  3330. << PP.getSpelling(Tok) << PragmaName << /*Expected=*/true
  3331. << "'on' or 'off'";
  3332. return false;
  3333. }
  3334. bool IsOn = II->isStr("on");
  3335. PP.Lex(Tok);
  3336. if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
  3337. PragmaName))
  3338. return false;
  3339. // TODO: Add support for "sgty"
  3340. if (!OptimizationList->getString().empty()) {
  3341. PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
  3342. << OptimizationList->getString() << PragmaName << /*Expected=*/true
  3343. << "\"\"";
  3344. return false;
  3345. }
  3346. if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
  3347. PragmaName))
  3348. return false;
  3349. Actions.ActOnPragmaMSOptimize(FirstTok.getLocation(), IsOn);
  3350. return true;
  3351. }
  3352. void PragmaForceCUDAHostDeviceHandler::HandlePragma(
  3353. Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
  3354. Token FirstTok = Tok;
  3355. PP.Lex(Tok);
  3356. IdentifierInfo *Info = Tok.getIdentifierInfo();
  3357. if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
  3358. PP.Diag(FirstTok.getLocation(),
  3359. diag::warn_pragma_force_cuda_host_device_bad_arg);
  3360. return;
  3361. }
  3362. if (Info->isStr("begin"))
  3363. Actions.PushForceCUDAHostDevice();
  3364. else if (!Actions.PopForceCUDAHostDevice())
  3365. PP.Diag(FirstTok.getLocation(),
  3366. diag::err_pragma_cannot_end_force_cuda_host_device);
  3367. PP.Lex(Tok);
  3368. if (!Tok.is(tok::eod))
  3369. PP.Diag(FirstTok.getLocation(),
  3370. diag::warn_pragma_force_cuda_host_device_bad_arg);
  3371. }
  3372. /// Handle the #pragma clang attribute directive.
  3373. ///
  3374. /// The syntax is:
  3375. /// \code
  3376. /// #pragma clang attribute push (attribute, subject-set)
  3377. /// #pragma clang attribute push
  3378. /// #pragma clang attribute (attribute, subject-set)
  3379. /// #pragma clang attribute pop
  3380. /// \endcode
  3381. ///
  3382. /// There are also 'namespace' variants of push and pop directives. The bare
  3383. /// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
  3384. /// namespace, since it always applies attributes to the most recently pushed
  3385. /// group, regardless of namespace.
  3386. /// \code
  3387. /// #pragma clang attribute namespace.push (attribute, subject-set)
  3388. /// #pragma clang attribute namespace.push
  3389. /// #pragma clang attribute namespace.pop
  3390. /// \endcode
  3391. ///
  3392. /// The subject-set clause defines the set of declarations which receive the
  3393. /// attribute. Its exact syntax is described in the LanguageExtensions document
  3394. /// in Clang's documentation.
  3395. ///
  3396. /// This directive instructs the compiler to begin/finish applying the specified
  3397. /// attribute to the set of attribute-specific declarations in the active range
  3398. /// of the pragma.
  3399. void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
  3400. PragmaIntroducer Introducer,
  3401. Token &FirstToken) {
  3402. Token Tok;
  3403. PP.Lex(Tok);
  3404. auto *Info = new (PP.getPreprocessorAllocator())
  3405. PragmaAttributeInfo(AttributesForPragmaAttribute);
  3406. // Parse the optional namespace followed by a period.
  3407. if (Tok.is(tok::identifier)) {
  3408. IdentifierInfo *II = Tok.getIdentifierInfo();
  3409. if (!II->isStr("push") && !II->isStr("pop")) {
  3410. Info->Namespace = II;
  3411. PP.Lex(Tok);
  3412. if (!Tok.is(tok::period)) {
  3413. PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
  3414. << II;
  3415. return;
  3416. }
  3417. PP.Lex(Tok);
  3418. }
  3419. }
  3420. if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
  3421. PP.Diag(Tok.getLocation(),
  3422. diag::err_pragma_attribute_expected_push_pop_paren);
  3423. return;
  3424. }
  3425. // Determine what action this pragma clang attribute represents.
  3426. if (Tok.is(tok::l_paren)) {
  3427. if (Info->Namespace) {
  3428. PP.Diag(Tok.getLocation(),
  3429. diag::err_pragma_attribute_namespace_on_attribute);
  3430. PP.Diag(Tok.getLocation(),
  3431. diag::note_pragma_attribute_namespace_on_attribute);
  3432. return;
  3433. }
  3434. Info->Action = PragmaAttributeInfo::Attribute;
  3435. } else {
  3436. const IdentifierInfo *II = Tok.getIdentifierInfo();
  3437. if (II->isStr("push"))
  3438. Info->Action = PragmaAttributeInfo::Push;
  3439. else if (II->isStr("pop"))
  3440. Info->Action = PragmaAttributeInfo::Pop;
  3441. else {
  3442. PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
  3443. << PP.getSpelling(Tok);
  3444. return;
  3445. }
  3446. PP.Lex(Tok);
  3447. }
  3448. // Parse the actual attribute.
  3449. if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
  3450. Info->Action == PragmaAttributeInfo::Attribute) {
  3451. if (Tok.isNot(tok::l_paren)) {
  3452. PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
  3453. return;
  3454. }
  3455. PP.Lex(Tok);
  3456. // Lex the attribute tokens.
  3457. SmallVector<Token, 16> AttributeTokens;
  3458. int OpenParens = 1;
  3459. while (Tok.isNot(tok::eod)) {
  3460. if (Tok.is(tok::l_paren))
  3461. OpenParens++;
  3462. else if (Tok.is(tok::r_paren)) {
  3463. OpenParens--;
  3464. if (OpenParens == 0)
  3465. break;
  3466. }
  3467. AttributeTokens.push_back(Tok);
  3468. PP.Lex(Tok);
  3469. }
  3470. if (AttributeTokens.empty()) {
  3471. PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
  3472. return;
  3473. }
  3474. if (Tok.isNot(tok::r_paren)) {
  3475. PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
  3476. return;
  3477. }
  3478. SourceLocation EndLoc = Tok.getLocation();
  3479. PP.Lex(Tok);
  3480. // Terminate the attribute for parsing.
  3481. Token EOFTok;
  3482. EOFTok.startToken();
  3483. EOFTok.setKind(tok::eof);
  3484. EOFTok.setLocation(EndLoc);
  3485. AttributeTokens.push_back(EOFTok);
  3486. markAsReinjectedForRelexing(AttributeTokens);
  3487. Info->Tokens =
  3488. llvm::ArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
  3489. }
  3490. if (Tok.isNot(tok::eod))
  3491. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  3492. << "clang attribute";
  3493. // Generate the annotated pragma token.
  3494. auto TokenArray = std::make_unique<Token[]>(1);
  3495. TokenArray[0].startToken();
  3496. TokenArray[0].setKind(tok::annot_pragma_attribute);
  3497. TokenArray[0].setLocation(FirstToken.getLocation());
  3498. TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
  3499. TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
  3500. PP.EnterTokenStream(std::move(TokenArray), 1,
  3501. /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
  3502. }
  3503. // Handle '#pragma clang max_tokens 12345'.
  3504. void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
  3505. PragmaIntroducer Introducer,
  3506. Token &Tok) {
  3507. PP.Lex(Tok);
  3508. if (Tok.is(tok::eod)) {
  3509. PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
  3510. << "clang max_tokens_here" << /*Expected=*/true << "integer";
  3511. return;
  3512. }
  3513. SourceLocation Loc = Tok.getLocation();
  3514. uint64_t MaxTokens;
  3515. if (Tok.isNot(tok::numeric_constant) ||
  3516. !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
  3517. PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
  3518. << "clang max_tokens_here";
  3519. return;
  3520. }
  3521. if (Tok.isNot(tok::eod)) {
  3522. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  3523. << "clang max_tokens_here";
  3524. return;
  3525. }
  3526. if (PP.getTokenCount() > MaxTokens) {
  3527. PP.Diag(Loc, diag::warn_max_tokens)
  3528. << PP.getTokenCount() << (unsigned)MaxTokens;
  3529. }
  3530. }
  3531. // Handle '#pragma clang max_tokens_total 12345'.
  3532. void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
  3533. PragmaIntroducer Introducer,
  3534. Token &Tok) {
  3535. PP.Lex(Tok);
  3536. if (Tok.is(tok::eod)) {
  3537. PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
  3538. << "clang max_tokens_total" << /*Expected=*/true << "integer";
  3539. return;
  3540. }
  3541. SourceLocation Loc = Tok.getLocation();
  3542. uint64_t MaxTokens;
  3543. if (Tok.isNot(tok::numeric_constant) ||
  3544. !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
  3545. PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
  3546. << "clang max_tokens_total";
  3547. return;
  3548. }
  3549. if (Tok.isNot(tok::eod)) {
  3550. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  3551. << "clang max_tokens_total";
  3552. return;
  3553. }
  3554. PP.overrideMaxTokens(MaxTokens, Loc);
  3555. }
  3556. // Handle '#pragma clang riscv intrinsic vector'.
  3557. void PragmaRISCVHandler::HandlePragma(Preprocessor &PP,
  3558. PragmaIntroducer Introducer,
  3559. Token &FirstToken) {
  3560. Token Tok;
  3561. PP.Lex(Tok);
  3562. IdentifierInfo *II = Tok.getIdentifierInfo();
  3563. if (!II || !II->isStr("intrinsic")) {
  3564. PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
  3565. << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'";
  3566. return;
  3567. }
  3568. PP.Lex(Tok);
  3569. II = Tok.getIdentifierInfo();
  3570. if (!II || !II->isStr("vector")) {
  3571. PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
  3572. << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'vector'";
  3573. return;
  3574. }
  3575. PP.Lex(Tok);
  3576. if (Tok.isNot(tok::eod)) {
  3577. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  3578. << "clang riscv intrinsic";
  3579. return;
  3580. }
  3581. Actions.DeclareRISCVVBuiltins = true;
  3582. }