ParsePragma.cpp 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236
  1. //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file implements the language specific #pragma handlers.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "RAIIObjectsForParser.h"
  14. #include "clang/AST/ASTContext.h"
  15. #include "clang/Basic/TargetInfo.h"
  16. #include "clang/Lex/Preprocessor.h"
  17. #include "clang/Parse/ParseDiagnostic.h"
  18. #include "clang/Parse/Parser.h"
  19. #include "clang/Sema/LoopHint.h"
  20. #include "clang/Sema/Scope.h"
  21. #include "llvm/ADT/StringSwitch.h"
  22. using namespace clang;
  23. namespace {
  24. struct PragmaAlignHandler : public PragmaHandler {
  25. explicit PragmaAlignHandler() : PragmaHandler("align") {}
  26. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  27. Token &FirstToken) override;
  28. };
  29. struct PragmaGCCVisibilityHandler : public PragmaHandler {
  30. explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
  31. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  32. Token &FirstToken) override;
  33. };
  34. struct PragmaOptionsHandler : public PragmaHandler {
  35. explicit PragmaOptionsHandler() : PragmaHandler("options") {}
  36. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  37. Token &FirstToken) override;
  38. };
  39. struct PragmaPackHandler : public PragmaHandler {
  40. explicit PragmaPackHandler() : PragmaHandler("pack") {}
  41. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  42. Token &FirstToken) override;
  43. };
  44. struct PragmaMSStructHandler : public PragmaHandler {
  45. explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
  46. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  47. Token &FirstToken) override;
  48. };
  49. struct PragmaUnusedHandler : public PragmaHandler {
  50. PragmaUnusedHandler() : PragmaHandler("unused") {}
  51. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  52. Token &FirstToken) override;
  53. };
  54. struct PragmaWeakHandler : public PragmaHandler {
  55. explicit PragmaWeakHandler() : PragmaHandler("weak") {}
  56. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  57. Token &FirstToken) override;
  58. };
  59. struct PragmaRedefineExtnameHandler : public PragmaHandler {
  60. explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
  61. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  62. Token &FirstToken) override;
  63. };
  64. struct PragmaOpenCLExtensionHandler : public PragmaHandler {
  65. PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
  66. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  67. Token &FirstToken) override;
  68. };
  69. struct PragmaFPContractHandler : public PragmaHandler {
  70. PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
  71. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  72. Token &FirstToken) override;
  73. };
  74. struct PragmaNoOpenMPHandler : public PragmaHandler {
  75. PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
  76. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  77. Token &FirstToken) override;
  78. };
  79. struct PragmaOpenMPHandler : public PragmaHandler {
  80. PragmaOpenMPHandler() : PragmaHandler("omp") { }
  81. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  82. Token &FirstToken) override;
  83. };
  84. /// PragmaCommentHandler - "\#pragma comment ...".
  85. struct PragmaCommentHandler : public PragmaHandler {
  86. PragmaCommentHandler(Sema &Actions)
  87. : PragmaHandler("comment"), Actions(Actions) {}
  88. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  89. Token &FirstToken) override;
  90. private:
  91. Sema &Actions;
  92. };
  93. struct PragmaDetectMismatchHandler : public PragmaHandler {
  94. PragmaDetectMismatchHandler(Sema &Actions)
  95. : PragmaHandler("detect_mismatch"), Actions(Actions) {}
  96. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  97. Token &FirstToken) override;
  98. private:
  99. Sema &Actions;
  100. };
  101. struct PragmaMSPointersToMembers : public PragmaHandler {
  102. explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
  103. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  104. Token &FirstToken) override;
  105. };
  106. struct PragmaMSVtorDisp : public PragmaHandler {
  107. explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
  108. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  109. Token &FirstToken) override;
  110. };
  111. struct PragmaMSPragma : public PragmaHandler {
  112. explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
  113. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  114. Token &FirstToken) override;
  115. };
  116. /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
  117. struct PragmaOptimizeHandler : public PragmaHandler {
  118. PragmaOptimizeHandler(Sema &S)
  119. : PragmaHandler("optimize"), Actions(S) {}
  120. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  121. Token &FirstToken) override;
  122. private:
  123. Sema &Actions;
  124. };
  125. struct PragmaLoopHintHandler : public PragmaHandler {
  126. PragmaLoopHintHandler() : PragmaHandler("loop") {}
  127. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  128. Token &FirstToken) override;
  129. };
  130. struct PragmaUnrollHintHandler : public PragmaHandler {
  131. PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
  132. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  133. Token &FirstToken) override;
  134. };
  135. struct PragmaPackMatrixHandler : public PragmaHandler {
  136. PragmaPackMatrixHandler(Sema &S) : PragmaHandler("pack_matrix"), Actions(S) {}
  137. void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
  138. Token &FirstToken) override;
  139. private:
  140. Sema &Actions;
  141. };
  142. } // end namespace
  143. void Parser::initializePragmaHandlers() {
  144. if (!getLangOpts().HLSL) { // HLSL Change
  145. // HLSL Note - Considering adding alignment support
  146. AlignHandler.reset(new PragmaAlignHandler());
  147. PP.AddPragmaHandler(AlignHandler.get());
  148. GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
  149. PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
  150. OptionsHandler.reset(new PragmaOptionsHandler());
  151. PP.AddPragmaHandler(OptionsHandler.get());
  152. PackHandler.reset(new PragmaPackHandler());
  153. PP.AddPragmaHandler(PackHandler.get());
  154. MSStructHandler.reset(new PragmaMSStructHandler());
  155. PP.AddPragmaHandler(MSStructHandler.get());
  156. UnusedHandler.reset(new PragmaUnusedHandler());
  157. PP.AddPragmaHandler(UnusedHandler.get());
  158. WeakHandler.reset(new PragmaWeakHandler());
  159. PP.AddPragmaHandler(WeakHandler.get());
  160. RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
  161. PP.AddPragmaHandler(RedefineExtnameHandler.get());
  162. FPContractHandler.reset(new PragmaFPContractHandler());
  163. PP.AddPragmaHandler("STDC", FPContractHandler.get());
  164. if (getLangOpts().OpenCL) {
  165. OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
  166. PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
  167. PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
  168. }
  169. if (getLangOpts().OpenMP)
  170. OpenMPHandler.reset(new PragmaOpenMPHandler());
  171. else
  172. OpenMPHandler.reset(new PragmaNoOpenMPHandler());
  173. PP.AddPragmaHandler(OpenMPHandler.get());
  174. if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
  175. MSCommentHandler.reset(new PragmaCommentHandler(Actions));
  176. PP.AddPragmaHandler(MSCommentHandler.get());
  177. }
  178. if (getLangOpts().MicrosoftExt) {
  179. MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
  180. PP.AddPragmaHandler(MSDetectMismatchHandler.get());
  181. MSPointersToMembers.reset(new PragmaMSPointersToMembers());
  182. PP.AddPragmaHandler(MSPointersToMembers.get());
  183. MSVtorDisp.reset(new PragmaMSVtorDisp());
  184. PP.AddPragmaHandler(MSVtorDisp.get());
  185. MSInitSeg.reset(new PragmaMSPragma("init_seg"));
  186. PP.AddPragmaHandler(MSInitSeg.get());
  187. MSDataSeg.reset(new PragmaMSPragma("data_seg"));
  188. PP.AddPragmaHandler(MSDataSeg.get());
  189. MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
  190. PP.AddPragmaHandler(MSBSSSeg.get());
  191. MSConstSeg.reset(new PragmaMSPragma("const_seg"));
  192. PP.AddPragmaHandler(MSConstSeg.get());
  193. MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
  194. PP.AddPragmaHandler(MSCodeSeg.get());
  195. MSSection.reset(new PragmaMSPragma("section"));
  196. PP.AddPragmaHandler(MSSection.get());
  197. }
  198. // HLSL Note - Considering adding alignment support
  199. OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
  200. PP.AddPragmaHandler("clang", OptimizeHandler.get());
  201. // HLSL Note - Considering adding alignment support
  202. LoopHintHandler.reset(new PragmaLoopHintHandler());
  203. PP.AddPragmaHandler("clang", LoopHintHandler.get());
  204. UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
  205. PP.AddPragmaHandler(UnrollHintHandler.get());
  206. NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
  207. PP.AddPragmaHandler(NoUnrollHintHandler.get());
  208. } // HLSL Change, matching HLSL check to remove pragma processing
  209. else {
  210. // HLSL Change Begin - packmatrix.
  211. // The pointer ownership goes to PP as soon as we do the call,
  212. // which deletes it in its destructor unless it is removed & deleted via resetPragmaHandlers
  213. pPackMatrixHandler = new PragmaPackMatrixHandler(Actions);
  214. PP.AddPragmaHandler(pPackMatrixHandler);
  215. // HLSL Change End.
  216. }
  217. }
  218. void Parser::resetPragmaHandlers() {
  219. if (!getLangOpts().HLSL) { // HLSL Change - open conditional for skipping pragmas
  220. // Remove the pragma handlers we installed.
  221. PP.RemovePragmaHandler(AlignHandler.get());
  222. AlignHandler.reset();
  223. PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
  224. GCCVisibilityHandler.reset();
  225. PP.RemovePragmaHandler(OptionsHandler.get());
  226. OptionsHandler.reset();
  227. PP.RemovePragmaHandler(PackHandler.get());
  228. PackHandler.reset();
  229. PP.RemovePragmaHandler(MSStructHandler.get());
  230. MSStructHandler.reset();
  231. PP.RemovePragmaHandler(UnusedHandler.get());
  232. UnusedHandler.reset();
  233. PP.RemovePragmaHandler(WeakHandler.get());
  234. WeakHandler.reset();
  235. PP.RemovePragmaHandler(RedefineExtnameHandler.get());
  236. RedefineExtnameHandler.reset();
  237. if (getLangOpts().OpenCL) {
  238. PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
  239. OpenCLExtensionHandler.reset();
  240. PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
  241. }
  242. PP.RemovePragmaHandler(OpenMPHandler.get());
  243. OpenMPHandler.reset();
  244. if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
  245. PP.RemovePragmaHandler(MSCommentHandler.get());
  246. MSCommentHandler.reset();
  247. }
  248. if (getLangOpts().MicrosoftExt) {
  249. PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
  250. MSDetectMismatchHandler.reset();
  251. PP.RemovePragmaHandler(MSPointersToMembers.get());
  252. MSPointersToMembers.reset();
  253. PP.RemovePragmaHandler(MSVtorDisp.get());
  254. MSVtorDisp.reset();
  255. PP.RemovePragmaHandler(MSInitSeg.get());
  256. MSInitSeg.reset();
  257. PP.RemovePragmaHandler(MSDataSeg.get());
  258. MSDataSeg.reset();
  259. PP.RemovePragmaHandler(MSBSSSeg.get());
  260. MSBSSSeg.reset();
  261. PP.RemovePragmaHandler(MSConstSeg.get());
  262. MSConstSeg.reset();
  263. PP.RemovePragmaHandler(MSCodeSeg.get());
  264. MSCodeSeg.reset();
  265. PP.RemovePragmaHandler(MSSection.get());
  266. MSSection.reset();
  267. }
  268. PP.RemovePragmaHandler("STDC", FPContractHandler.get());
  269. FPContractHandler.reset();
  270. PP.RemovePragmaHandler("clang", OptimizeHandler.get());
  271. OptimizeHandler.reset();
  272. PP.RemovePragmaHandler("clang", LoopHintHandler.get());
  273. LoopHintHandler.reset();
  274. PP.RemovePragmaHandler(UnrollHintHandler.get());
  275. UnrollHintHandler.reset();
  276. PP.RemovePragmaHandler(NoUnrollHintHandler.get());
  277. NoUnrollHintHandler.reset();
  278. } // HLSL Change - close conditional for skipping pragmas
  279. else {
  280. // HLSL Change Begin - packmatrix.
  281. PP.RemovePragmaHandler(pPackMatrixHandler);
  282. delete pPackMatrixHandler;
  283. pPackMatrixHandler = nullptr;
  284. // HLSL Change End.
  285. }
  286. }
  287. /// \brief Handle the annotation token produced for #pragma unused(...)
  288. ///
  289. /// Each annot_pragma_unused is followed by the argument token so e.g.
  290. /// "#pragma unused(x,y)" becomes:
  291. /// annot_pragma_unused 'x' annot_pragma_unused 'y'
  292. void Parser::HandlePragmaUnused() {
  293. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  294. assert(Tok.is(tok::annot_pragma_unused));
  295. SourceLocation UnusedLoc = ConsumeToken();
  296. Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
  297. ConsumeToken(); // The argument token.
  298. }
  299. void Parser::HandlePragmaVisibility() {
  300. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  301. assert(Tok.is(tok::annot_pragma_vis));
  302. const IdentifierInfo *VisType =
  303. static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
  304. SourceLocation VisLoc = ConsumeToken();
  305. Actions.ActOnPragmaVisibility(VisType, VisLoc);
  306. }
  307. struct PragmaPackInfo {
  308. Sema::PragmaPackKind Kind;
  309. IdentifierInfo *Name;
  310. Token Alignment;
  311. SourceLocation LParenLoc;
  312. SourceLocation RParenLoc;
  313. };
  314. void Parser::HandlePragmaPack() {
  315. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  316. assert(Tok.is(tok::annot_pragma_pack));
  317. PragmaPackInfo *Info =
  318. static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
  319. SourceLocation PragmaLoc = ConsumeToken();
  320. ExprResult Alignment;
  321. if (Info->Alignment.is(tok::numeric_constant)) {
  322. Alignment = Actions.ActOnNumericConstant(Info->Alignment);
  323. if (Alignment.isInvalid())
  324. return;
  325. }
  326. Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
  327. Info->LParenLoc, Info->RParenLoc);
  328. }
  329. void Parser::HandlePragmaMSStruct() {
  330. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  331. assert(Tok.is(tok::annot_pragma_msstruct));
  332. Sema::PragmaMSStructKind Kind =
  333. static_cast<Sema::PragmaMSStructKind>(
  334. reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
  335. Actions.ActOnPragmaMSStruct(Kind);
  336. ConsumeToken(); // The annotation token.
  337. }
  338. void Parser::HandlePragmaAlign() {
  339. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  340. assert(Tok.is(tok::annot_pragma_align));
  341. Sema::PragmaOptionsAlignKind Kind =
  342. static_cast<Sema::PragmaOptionsAlignKind>(
  343. reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
  344. SourceLocation PragmaLoc = ConsumeToken();
  345. Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
  346. }
  347. void Parser::HandlePragmaWeak() {
  348. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  349. assert(Tok.is(tok::annot_pragma_weak));
  350. SourceLocation PragmaLoc = ConsumeToken();
  351. Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
  352. Tok.getLocation());
  353. ConsumeToken(); // The weak name.
  354. }
  355. void Parser::HandlePragmaWeakAlias() {
  356. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  357. assert(Tok.is(tok::annot_pragma_weakalias));
  358. SourceLocation PragmaLoc = ConsumeToken();
  359. IdentifierInfo *WeakName = Tok.getIdentifierInfo();
  360. SourceLocation WeakNameLoc = Tok.getLocation();
  361. ConsumeToken();
  362. IdentifierInfo *AliasName = Tok.getIdentifierInfo();
  363. SourceLocation AliasNameLoc = Tok.getLocation();
  364. ConsumeToken();
  365. Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
  366. WeakNameLoc, AliasNameLoc);
  367. }
  368. void Parser::HandlePragmaRedefineExtname() {
  369. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  370. assert(Tok.is(tok::annot_pragma_redefine_extname));
  371. SourceLocation RedefLoc = ConsumeToken();
  372. IdentifierInfo *RedefName = Tok.getIdentifierInfo();
  373. SourceLocation RedefNameLoc = Tok.getLocation();
  374. ConsumeToken();
  375. IdentifierInfo *AliasName = Tok.getIdentifierInfo();
  376. SourceLocation AliasNameLoc = Tok.getLocation();
  377. ConsumeToken();
  378. Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
  379. RedefNameLoc, AliasNameLoc);
  380. }
  381. void Parser::HandlePragmaFPContract() {
  382. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  383. assert(Tok.is(tok::annot_pragma_fp_contract));
  384. tok::OnOffSwitch OOS =
  385. static_cast<tok::OnOffSwitch>(
  386. reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
  387. Actions.ActOnPragmaFPContract(OOS);
  388. ConsumeToken(); // The annotation token.
  389. }
  390. StmtResult Parser::HandlePragmaCaptured()
  391. {
  392. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  393. assert(Tok.is(tok::annot_pragma_captured));
  394. ConsumeToken();
  395. if (Tok.isNot(tok::l_brace)) {
  396. PP.Diag(Tok, diag::err_expected) << tok::l_brace;
  397. return StmtError();
  398. }
  399. SourceLocation Loc = Tok.getLocation();
  400. ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
  401. Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
  402. /*NumParams=*/1);
  403. StmtResult R = ParseCompoundStatement();
  404. CapturedRegionScope.Exit();
  405. if (R.isInvalid()) {
  406. Actions.ActOnCapturedRegionError();
  407. return StmtError();
  408. }
  409. return Actions.ActOnCapturedRegionEnd(R.get());
  410. }
  411. namespace {
  412. typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
  413. }
  414. void Parser::HandlePragmaOpenCLExtension() {
  415. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  416. assert(Tok.is(tok::annot_pragma_opencl_extension));
  417. OpenCLExtData data =
  418. OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
  419. unsigned state = data.getInt();
  420. IdentifierInfo *ename = data.getPointer();
  421. SourceLocation NameLoc = Tok.getLocation();
  422. ConsumeToken(); // The annotation token.
  423. OpenCLOptions &f = Actions.getOpenCLOptions();
  424. // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
  425. // overriding all previously issued extension directives, but only if the
  426. // behavior is set to disable."
  427. if (state == 0 && ename->isStr("all")) {
  428. #define OPENCLEXT(nm) f.nm = 0;
  429. #include "clang/Basic/OpenCLExtensions.def"
  430. }
  431. #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
  432. #include "clang/Basic/OpenCLExtensions.def"
  433. else {
  434. PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
  435. return;
  436. }
  437. }
  438. void Parser::HandlePragmaMSPointersToMembers() {
  439. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  440. assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
  441. LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
  442. static_cast<LangOptions::PragmaMSPointersToMembersKind>(
  443. reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
  444. SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
  445. Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
  446. }
  447. void Parser::HandlePragmaMSVtorDisp() {
  448. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  449. assert(Tok.is(tok::annot_pragma_ms_vtordisp));
  450. uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
  451. Sema::PragmaVtorDispKind Kind =
  452. static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
  453. MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
  454. SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
  455. Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
  456. }
  457. void Parser::HandlePragmaMSPragma() {
  458. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  459. assert(Tok.is(tok::annot_pragma_ms_pragma));
  460. // Grab the tokens out of the annotation and enter them into the stream.
  461. auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
  462. PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
  463. SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
  464. assert(Tok.isAnyIdentifier());
  465. StringRef PragmaName = Tok.getIdentifierInfo()->getName();
  466. PP.Lex(Tok); // pragma kind
  467. // Figure out which #pragma we're dealing with. The switch has no default
  468. // because lex shouldn't emit the annotation token for unrecognized pragmas.
  469. typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
  470. PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
  471. .Case("data_seg", &Parser::HandlePragmaMSSegment)
  472. .Case("bss_seg", &Parser::HandlePragmaMSSegment)
  473. .Case("const_seg", &Parser::HandlePragmaMSSegment)
  474. .Case("code_seg", &Parser::HandlePragmaMSSegment)
  475. .Case("section", &Parser::HandlePragmaMSSection)
  476. .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
  477. if (!(this->*Handler)(PragmaName, PragmaLocation)) {
  478. // Pragma handling failed, and has been diagnosed. Slurp up the tokens
  479. // until eof (really end of line) to prevent follow-on errors.
  480. while (Tok.isNot(tok::eof))
  481. PP.Lex(Tok);
  482. PP.Lex(Tok);
  483. }
  484. }
  485. bool Parser::HandlePragmaMSSection(StringRef PragmaName,
  486. SourceLocation PragmaLocation) {
  487. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  488. if (Tok.isNot(tok::l_paren)) {
  489. PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
  490. return false;
  491. }
  492. PP.Lex(Tok); // (
  493. // Parsing code for pragma section
  494. if (Tok.isNot(tok::string_literal)) {
  495. PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
  496. << PragmaName;
  497. return false;
  498. }
  499. ExprResult StringResult = ParseStringLiteralExpression();
  500. if (StringResult.isInvalid())
  501. return false; // Already diagnosed.
  502. StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
  503. if (SegmentName->getCharByteWidth() != 1) {
  504. PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
  505. << PragmaName;
  506. return false;
  507. }
  508. int SectionFlags = ASTContext::PSF_Read;
  509. bool SectionFlagsAreDefault = true;
  510. while (Tok.is(tok::comma)) {
  511. PP.Lex(Tok); // ,
  512. // Ignore "long" and "short".
  513. // They are undocumented, but widely used, section attributes which appear
  514. // to do nothing.
  515. if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
  516. PP.Lex(Tok); // long/short
  517. continue;
  518. }
  519. if (!Tok.isAnyIdentifier()) {
  520. PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
  521. << PragmaName;
  522. return false;
  523. }
  524. ASTContext::PragmaSectionFlag Flag =
  525. llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
  526. Tok.getIdentifierInfo()->getName())
  527. .Case("read", ASTContext::PSF_Read)
  528. .Case("write", ASTContext::PSF_Write)
  529. .Case("execute", ASTContext::PSF_Execute)
  530. .Case("shared", ASTContext::PSF_Invalid)
  531. .Case("nopage", ASTContext::PSF_Invalid)
  532. .Case("nocache", ASTContext::PSF_Invalid)
  533. .Case("discard", ASTContext::PSF_Invalid)
  534. .Case("remove", ASTContext::PSF_Invalid)
  535. .Default(ASTContext::PSF_None);
  536. if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
  537. PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
  538. ? diag::warn_pragma_invalid_specific_action
  539. : diag::warn_pragma_unsupported_action)
  540. << PragmaName << Tok.getIdentifierInfo()->getName();
  541. return false;
  542. }
  543. SectionFlags |= Flag;
  544. SectionFlagsAreDefault = false;
  545. PP.Lex(Tok); // Identifier
  546. }
  547. // If no section attributes are specified, the section will be marked as
  548. // read/write.
  549. if (SectionFlagsAreDefault)
  550. SectionFlags |= ASTContext::PSF_Write;
  551. if (Tok.isNot(tok::r_paren)) {
  552. PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
  553. return false;
  554. }
  555. PP.Lex(Tok); // )
  556. if (Tok.isNot(tok::eof)) {
  557. PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
  558. << PragmaName;
  559. return false;
  560. }
  561. PP.Lex(Tok); // eof
  562. Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
  563. return true;
  564. }
  565. bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
  566. SourceLocation PragmaLocation) {
  567. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  568. if (Tok.isNot(tok::l_paren)) {
  569. PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
  570. return false;
  571. }
  572. PP.Lex(Tok); // (
  573. Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
  574. StringRef SlotLabel;
  575. if (Tok.isAnyIdentifier()) {
  576. StringRef PushPop = Tok.getIdentifierInfo()->getName();
  577. if (PushPop == "push")
  578. Action = Sema::PSK_Push;
  579. else if (PushPop == "pop")
  580. Action = Sema::PSK_Pop;
  581. else {
  582. PP.Diag(PragmaLocation,
  583. diag::warn_pragma_expected_section_push_pop_or_name)
  584. << PragmaName;
  585. return false;
  586. }
  587. if (Action != Sema::PSK_Reset) {
  588. PP.Lex(Tok); // push | pop
  589. if (Tok.is(tok::comma)) {
  590. PP.Lex(Tok); // ,
  591. // If we've got a comma, we either need a label or a string.
  592. if (Tok.isAnyIdentifier()) {
  593. SlotLabel = Tok.getIdentifierInfo()->getName();
  594. PP.Lex(Tok); // identifier
  595. if (Tok.is(tok::comma))
  596. PP.Lex(Tok);
  597. else if (Tok.isNot(tok::r_paren)) {
  598. PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
  599. << PragmaName;
  600. return false;
  601. }
  602. }
  603. } else if (Tok.isNot(tok::r_paren)) {
  604. PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
  605. return false;
  606. }
  607. }
  608. }
  609. // Grab the string literal for our section name.
  610. StringLiteral *SegmentName = nullptr;
  611. if (Tok.isNot(tok::r_paren)) {
  612. if (Tok.isNot(tok::string_literal)) {
  613. unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
  614. diag::warn_pragma_expected_section_name :
  615. diag::warn_pragma_expected_section_label_or_name :
  616. diag::warn_pragma_expected_section_push_pop_or_name;
  617. PP.Diag(PragmaLocation, DiagID) << PragmaName;
  618. return false;
  619. }
  620. ExprResult StringResult = ParseStringLiteralExpression();
  621. if (StringResult.isInvalid())
  622. return false; // Already diagnosed.
  623. SegmentName = cast<StringLiteral>(StringResult.get());
  624. if (SegmentName->getCharByteWidth() != 1) {
  625. PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
  626. << PragmaName;
  627. return false;
  628. }
  629. // Setting section "" has no effect
  630. if (SegmentName->getLength())
  631. Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
  632. }
  633. if (Tok.isNot(tok::r_paren)) {
  634. PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
  635. return false;
  636. }
  637. PP.Lex(Tok); // )
  638. if (Tok.isNot(tok::eof)) {
  639. PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
  640. << PragmaName;
  641. return false;
  642. }
  643. PP.Lex(Tok); // eof
  644. Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
  645. SegmentName, PragmaName);
  646. return true;
  647. }
  648. // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
  649. bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
  650. SourceLocation PragmaLocation) {
  651. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  652. if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
  653. PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
  654. return false;
  655. }
  656. if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
  657. PragmaName))
  658. return false;
  659. // Parse either the known section names or the string section name.
  660. StringLiteral *SegmentName = nullptr;
  661. if (Tok.isAnyIdentifier()) {
  662. auto *II = Tok.getIdentifierInfo();
  663. StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
  664. .Case("compiler", "\".CRT$XCC\"")
  665. .Case("lib", "\".CRT$XCL\"")
  666. .Case("user", "\".CRT$XCU\"")
  667. .Default("");
  668. if (!Section.empty()) {
  669. // Pretend the user wrote the appropriate string literal here.
  670. Token Toks[1];
  671. Toks[0].startToken();
  672. Toks[0].setKind(tok::string_literal);
  673. Toks[0].setLocation(Tok.getLocation());
  674. Toks[0].setLiteralData(Section.data());
  675. Toks[0].setLength(Section.size());
  676. SegmentName =
  677. cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
  678. PP.Lex(Tok);
  679. }
  680. } else if (Tok.is(tok::string_literal)) {
  681. ExprResult StringResult = ParseStringLiteralExpression();
  682. if (StringResult.isInvalid())
  683. return false;
  684. SegmentName = cast<StringLiteral>(StringResult.get());
  685. if (SegmentName->getCharByteWidth() != 1) {
  686. PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
  687. << PragmaName;
  688. return false;
  689. }
  690. // FIXME: Add support for the '[, func-name]' part of the pragma.
  691. }
  692. if (!SegmentName) {
  693. PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
  694. return false;
  695. }
  696. if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
  697. PragmaName) ||
  698. ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
  699. PragmaName))
  700. return false;
  701. Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
  702. return true;
  703. }
  704. struct PragmaLoopHintInfo {
  705. Token PragmaName;
  706. Token Option;
  707. Token *Toks;
  708. size_t TokSize;
  709. PragmaLoopHintInfo() : Toks(nullptr), TokSize(0) {}
  710. };
  711. static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
  712. std::string PragmaString;
  713. if (PragmaName.getIdentifierInfo()->getName() == "loop") {
  714. PragmaString = "clang loop ";
  715. PragmaString += Option.getIdentifierInfo()->getName();
  716. } else {
  717. assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
  718. "Unexpected pragma name");
  719. PragmaString = "unroll";
  720. }
  721. return PragmaString;
  722. }
  723. bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
  724. assert(!getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  725. assert(Tok.is(tok::annot_pragma_loop_hint));
  726. PragmaLoopHintInfo *Info =
  727. static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
  728. IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
  729. Hint.PragmaNameLoc = IdentifierLoc::create(
  730. Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
  731. // It is possible that the loop hint has no option identifier, such as
  732. // #pragma unroll(4).
  733. IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
  734. ? Info->Option.getIdentifierInfo()
  735. : nullptr;
  736. Hint.OptionLoc = IdentifierLoc::create(
  737. Actions.Context, Info->Option.getLocation(), OptionInfo);
  738. Token *Toks = Info->Toks;
  739. size_t TokSize = Info->TokSize;
  740. // Return a valid hint if pragma unroll or nounroll were specified
  741. // without an argument.
  742. bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
  743. bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
  744. if (TokSize == 0 && (PragmaUnroll || PragmaNoUnroll)) {
  745. ConsumeToken(); // The annotation token.
  746. Hint.Range = Info->PragmaName.getLocation();
  747. return true;
  748. }
  749. // The constant expression is always followed by an eof token, which increases
  750. // the TokSize by 1.
  751. assert(TokSize > 0 &&
  752. "PragmaLoopHintInfo::Toks must contain at least one token.");
  753. // If no option is specified the argument is assumed to be a constant expr.
  754. bool OptionUnroll = false;
  755. bool StateOption = false;
  756. if (OptionInfo) { // Pragma Unroll does not specify an option.
  757. OptionUnroll = OptionInfo->isStr("unroll");
  758. StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
  759. .Case("vectorize", true)
  760. .Case("interleave", true)
  761. .Case("unroll", true)
  762. .Default(false);
  763. }
  764. // Verify loop hint has an argument.
  765. if (Toks[0].is(tok::eof)) {
  766. ConsumeToken(); // The annotation token.
  767. Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
  768. << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll;
  769. return false;
  770. }
  771. // Validate the argument.
  772. if (StateOption) {
  773. ConsumeToken(); // The annotation token.
  774. SourceLocation StateLoc = Toks[0].getLocation();
  775. IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
  776. if (!StateInfo ||
  777. ((OptionUnroll ? !StateInfo->isStr("full")
  778. : !StateInfo->isStr("enable") &&
  779. !StateInfo->isStr("assume_safety")) &&
  780. !StateInfo->isStr("disable"))) {
  781. Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
  782. << /*FullKeyword=*/OptionUnroll;
  783. return false;
  784. }
  785. if (TokSize > 2)
  786. Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  787. << PragmaLoopHintString(Info->PragmaName, Info->Option);
  788. Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
  789. } else {
  790. // Enter constant expression including eof terminator into token stream.
  791. PP.EnterTokenStream(Toks, TokSize, /*DisableMacroExpansion=*/false,
  792. /*OwnsTokens=*/false);
  793. ConsumeToken(); // The annotation token.
  794. ExprResult R = ParseConstantExpression();
  795. // Tokens following an error in an ill-formed constant expression will
  796. // remain in the token stream and must be removed.
  797. if (Tok.isNot(tok::eof)) {
  798. Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  799. << PragmaLoopHintString(Info->PragmaName, Info->Option);
  800. while (Tok.isNot(tok::eof))
  801. ConsumeAnyToken();
  802. }
  803. ConsumeToken(); // Consume the constant expression eof terminator.
  804. if (R.isInvalid() ||
  805. Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
  806. return false;
  807. // Argument is a constant expression with an integer type.
  808. Hint.ValueExpr = R.get();
  809. }
  810. Hint.Range = SourceRange(Info->PragmaName.getLocation(),
  811. Info->Toks[TokSize - 1].getLocation());
  812. return true;
  813. }
  814. // #pragma GCC visibility comes in two variants:
  815. // 'push' '(' [visibility] ')'
  816. // 'pop'
  817. void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
  818. PragmaIntroducerKind Introducer,
  819. Token &VisTok) {
  820. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  821. SourceLocation VisLoc = VisTok.getLocation();
  822. Token Tok;
  823. PP.LexUnexpandedToken(Tok);
  824. const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
  825. const IdentifierInfo *VisType;
  826. if (PushPop && PushPop->isStr("pop")) {
  827. VisType = nullptr;
  828. } else if (PushPop && PushPop->isStr("push")) {
  829. PP.LexUnexpandedToken(Tok);
  830. if (Tok.isNot(tok::l_paren)) {
  831. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
  832. << "visibility";
  833. return;
  834. }
  835. PP.LexUnexpandedToken(Tok);
  836. VisType = Tok.getIdentifierInfo();
  837. if (!VisType) {
  838. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  839. << "visibility";
  840. return;
  841. }
  842. PP.LexUnexpandedToken(Tok);
  843. if (Tok.isNot(tok::r_paren)) {
  844. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
  845. << "visibility";
  846. return;
  847. }
  848. } else {
  849. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  850. << "visibility";
  851. return;
  852. }
  853. SourceLocation EndLoc = Tok.getLocation();
  854. PP.LexUnexpandedToken(Tok);
  855. if (Tok.isNot(tok::eod)) {
  856. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  857. << "visibility";
  858. return;
  859. }
  860. Token *Toks = new Token[1];
  861. Toks[0].startToken();
  862. Toks[0].setKind(tok::annot_pragma_vis);
  863. Toks[0].setLocation(VisLoc);
  864. Toks[0].setAnnotationEndLoc(EndLoc);
  865. Toks[0].setAnnotationValue(
  866. const_cast<void*>(static_cast<const void*>(VisType)));
  867. PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
  868. /*OwnsTokens=*/true);
  869. }
  870. // #pragma pack(...) comes in the following delicious flavors:
  871. // pack '(' [integer] ')'
  872. // pack '(' 'show' ')'
  873. // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
  874. void PragmaPackHandler::HandlePragma(Preprocessor &PP,
  875. PragmaIntroducerKind Introducer,
  876. Token &PackTok) {
  877. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  878. SourceLocation PackLoc = PackTok.getLocation();
  879. Token Tok;
  880. PP.Lex(Tok);
  881. if (Tok.isNot(tok::l_paren)) {
  882. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
  883. return;
  884. }
  885. Sema::PragmaPackKind Kind = Sema::PPK_Default;
  886. IdentifierInfo *Name = nullptr;
  887. Token Alignment;
  888. Alignment.startToken();
  889. SourceLocation LParenLoc = Tok.getLocation();
  890. PP.Lex(Tok);
  891. if (Tok.is(tok::numeric_constant)) {
  892. Alignment = Tok;
  893. PP.Lex(Tok);
  894. // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
  895. // the push/pop stack.
  896. // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
  897. if (PP.getLangOpts().ApplePragmaPack)
  898. Kind = Sema::PPK_Push;
  899. } else if (Tok.is(tok::identifier)) {
  900. const IdentifierInfo *II = Tok.getIdentifierInfo();
  901. if (II->isStr("show")) {
  902. Kind = Sema::PPK_Show;
  903. PP.Lex(Tok);
  904. } else {
  905. if (II->isStr("push")) {
  906. Kind = Sema::PPK_Push;
  907. } else if (II->isStr("pop")) {
  908. Kind = Sema::PPK_Pop;
  909. } else {
  910. PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
  911. return;
  912. }
  913. PP.Lex(Tok);
  914. if (Tok.is(tok::comma)) {
  915. PP.Lex(Tok);
  916. if (Tok.is(tok::numeric_constant)) {
  917. Alignment = Tok;
  918. PP.Lex(Tok);
  919. } else if (Tok.is(tok::identifier)) {
  920. Name = Tok.getIdentifierInfo();
  921. PP.Lex(Tok);
  922. if (Tok.is(tok::comma)) {
  923. PP.Lex(Tok);
  924. if (Tok.isNot(tok::numeric_constant)) {
  925. PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
  926. return;
  927. }
  928. Alignment = Tok;
  929. PP.Lex(Tok);
  930. }
  931. } else {
  932. PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
  933. return;
  934. }
  935. }
  936. }
  937. } else if (PP.getLangOpts().ApplePragmaPack) {
  938. // In MSVC/gcc, #pragma pack() resets the alignment without affecting
  939. // the push/pop stack.
  940. // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
  941. Kind = Sema::PPK_Pop;
  942. }
  943. if (Tok.isNot(tok::r_paren)) {
  944. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
  945. return;
  946. }
  947. SourceLocation RParenLoc = Tok.getLocation();
  948. PP.Lex(Tok);
  949. if (Tok.isNot(tok::eod)) {
  950. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
  951. return;
  952. }
  953. PragmaPackInfo *Info =
  954. (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
  955. sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
  956. new (Info) PragmaPackInfo();
  957. Info->Kind = Kind;
  958. Info->Name = Name;
  959. Info->Alignment = Alignment;
  960. Info->LParenLoc = LParenLoc;
  961. Info->RParenLoc = RParenLoc;
  962. Token *Toks =
  963. (Token*) PP.getPreprocessorAllocator().Allocate(
  964. sizeof(Token) * 1, llvm::alignOf<Token>());
  965. new (Toks) Token();
  966. Toks[0].startToken();
  967. Toks[0].setKind(tok::annot_pragma_pack);
  968. Toks[0].setLocation(PackLoc);
  969. Toks[0].setAnnotationEndLoc(RParenLoc);
  970. Toks[0].setAnnotationValue(static_cast<void*>(Info));
  971. PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
  972. /*OwnsTokens=*/false);
  973. }
  974. // #pragma ms_struct on
  975. // #pragma ms_struct off
  976. void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
  977. PragmaIntroducerKind Introducer,
  978. Token &MSStructTok) {
  979. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  980. Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
  981. Token Tok;
  982. PP.Lex(Tok);
  983. if (Tok.isNot(tok::identifier)) {
  984. PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
  985. return;
  986. }
  987. SourceLocation EndLoc = Tok.getLocation();
  988. const IdentifierInfo *II = Tok.getIdentifierInfo();
  989. if (II->isStr("on")) {
  990. Kind = Sema::PMSST_ON;
  991. PP.Lex(Tok);
  992. }
  993. else if (II->isStr("off") || II->isStr("reset"))
  994. PP.Lex(Tok);
  995. else {
  996. PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
  997. return;
  998. }
  999. if (Tok.isNot(tok::eod)) {
  1000. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1001. << "ms_struct";
  1002. return;
  1003. }
  1004. Token *Toks =
  1005. (Token*) PP.getPreprocessorAllocator().Allocate(
  1006. sizeof(Token) * 1, llvm::alignOf<Token>());
  1007. new (Toks) Token();
  1008. Toks[0].startToken();
  1009. Toks[0].setKind(tok::annot_pragma_msstruct);
  1010. Toks[0].setLocation(MSStructTok.getLocation());
  1011. Toks[0].setAnnotationEndLoc(EndLoc);
  1012. Toks[0].setAnnotationValue(reinterpret_cast<void*>(
  1013. static_cast<uintptr_t>(Kind)));
  1014. PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
  1015. /*OwnsTokens=*/false);
  1016. }
  1017. // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
  1018. // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
  1019. static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
  1020. bool IsOptions) {
  1021. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1022. Token Tok;
  1023. if (IsOptions) {
  1024. PP.Lex(Tok);
  1025. if (Tok.isNot(tok::identifier) ||
  1026. !Tok.getIdentifierInfo()->isStr("align")) {
  1027. PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
  1028. return;
  1029. }
  1030. }
  1031. PP.Lex(Tok);
  1032. if (Tok.isNot(tok::equal)) {
  1033. PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
  1034. << IsOptions;
  1035. return;
  1036. }
  1037. PP.Lex(Tok);
  1038. if (Tok.isNot(tok::identifier)) {
  1039. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  1040. << (IsOptions ? "options" : "align");
  1041. return;
  1042. }
  1043. Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
  1044. const IdentifierInfo *II = Tok.getIdentifierInfo();
  1045. if (II->isStr("native"))
  1046. Kind = Sema::POAK_Native;
  1047. else if (II->isStr("natural"))
  1048. Kind = Sema::POAK_Natural;
  1049. else if (II->isStr("packed"))
  1050. Kind = Sema::POAK_Packed;
  1051. else if (II->isStr("power"))
  1052. Kind = Sema::POAK_Power;
  1053. else if (II->isStr("mac68k"))
  1054. Kind = Sema::POAK_Mac68k;
  1055. else if (II->isStr("reset"))
  1056. Kind = Sema::POAK_Reset;
  1057. else {
  1058. PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
  1059. << IsOptions;
  1060. return;
  1061. }
  1062. SourceLocation EndLoc = Tok.getLocation();
  1063. PP.Lex(Tok);
  1064. if (Tok.isNot(tok::eod)) {
  1065. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1066. << (IsOptions ? "options" : "align");
  1067. return;
  1068. }
  1069. Token *Toks =
  1070. (Token*) PP.getPreprocessorAllocator().Allocate(
  1071. sizeof(Token) * 1, llvm::alignOf<Token>());
  1072. new (Toks) Token();
  1073. Toks[0].startToken();
  1074. Toks[0].setKind(tok::annot_pragma_align);
  1075. Toks[0].setLocation(FirstTok.getLocation());
  1076. Toks[0].setAnnotationEndLoc(EndLoc);
  1077. Toks[0].setAnnotationValue(reinterpret_cast<void*>(
  1078. static_cast<uintptr_t>(Kind)));
  1079. PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
  1080. /*OwnsTokens=*/false);
  1081. }
  1082. void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
  1083. PragmaIntroducerKind Introducer,
  1084. Token &AlignTok) {
  1085. ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
  1086. }
  1087. void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
  1088. PragmaIntroducerKind Introducer,
  1089. Token &OptionsTok) {
  1090. ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
  1091. }
  1092. // #pragma unused(identifier)
  1093. void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
  1094. PragmaIntroducerKind Introducer,
  1095. Token &UnusedTok) {
  1096. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1097. // FIXME: Should we be expanding macros here? My guess is no.
  1098. SourceLocation UnusedLoc = UnusedTok.getLocation();
  1099. // Lex the left '('.
  1100. Token Tok;
  1101. PP.Lex(Tok);
  1102. if (Tok.isNot(tok::l_paren)) {
  1103. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
  1104. return;
  1105. }
  1106. // Lex the declaration reference(s).
  1107. SmallVector<Token, 5> Identifiers;
  1108. SourceLocation RParenLoc;
  1109. bool LexID = true;
  1110. while (true) {
  1111. PP.Lex(Tok);
  1112. if (LexID) {
  1113. if (Tok.is(tok::identifier)) {
  1114. Identifiers.push_back(Tok);
  1115. LexID = false;
  1116. continue;
  1117. }
  1118. // Illegal token!
  1119. PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
  1120. return;
  1121. }
  1122. // We are execting a ')' or a ','.
  1123. if (Tok.is(tok::comma)) {
  1124. LexID = true;
  1125. continue;
  1126. }
  1127. if (Tok.is(tok::r_paren)) {
  1128. RParenLoc = Tok.getLocation();
  1129. break;
  1130. }
  1131. // Illegal token!
  1132. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
  1133. return;
  1134. }
  1135. PP.Lex(Tok);
  1136. if (Tok.isNot(tok::eod)) {
  1137. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
  1138. "unused";
  1139. return;
  1140. }
  1141. // Verify that we have a location for the right parenthesis.
  1142. assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
  1143. assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
  1144. // For each identifier token, insert into the token stream a
  1145. // annot_pragma_unused token followed by the identifier token.
  1146. // This allows us to cache a "#pragma unused" that occurs inside an inline
  1147. // C++ member function.
  1148. Token *Toks =
  1149. (Token*) PP.getPreprocessorAllocator().Allocate(
  1150. sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
  1151. for (unsigned i=0; i != Identifiers.size(); i++) {
  1152. Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
  1153. pragmaUnusedTok.startToken();
  1154. pragmaUnusedTok.setKind(tok::annot_pragma_unused);
  1155. pragmaUnusedTok.setLocation(UnusedLoc);
  1156. idTok = Identifiers[i];
  1157. }
  1158. PP.EnterTokenStream(Toks, 2*Identifiers.size(),
  1159. /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
  1160. }
  1161. // #pragma weak identifier
  1162. // #pragma weak identifier '=' identifier
  1163. void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
  1164. PragmaIntroducerKind Introducer,
  1165. Token &WeakTok) {
  1166. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1167. SourceLocation WeakLoc = WeakTok.getLocation();
  1168. Token Tok;
  1169. PP.Lex(Tok);
  1170. if (Tok.isNot(tok::identifier)) {
  1171. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
  1172. return;
  1173. }
  1174. Token WeakName = Tok;
  1175. bool HasAlias = false;
  1176. Token AliasName;
  1177. PP.Lex(Tok);
  1178. if (Tok.is(tok::equal)) {
  1179. HasAlias = true;
  1180. PP.Lex(Tok);
  1181. if (Tok.isNot(tok::identifier)) {
  1182. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  1183. << "weak";
  1184. return;
  1185. }
  1186. AliasName = Tok;
  1187. PP.Lex(Tok);
  1188. }
  1189. if (Tok.isNot(tok::eod)) {
  1190. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
  1191. return;
  1192. }
  1193. if (HasAlias) {
  1194. Token *Toks =
  1195. (Token*) PP.getPreprocessorAllocator().Allocate(
  1196. sizeof(Token) * 3, llvm::alignOf<Token>());
  1197. Token &pragmaUnusedTok = Toks[0];
  1198. pragmaUnusedTok.startToken();
  1199. pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
  1200. pragmaUnusedTok.setLocation(WeakLoc);
  1201. pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
  1202. Toks[1] = WeakName;
  1203. Toks[2] = AliasName;
  1204. PP.EnterTokenStream(Toks, 3,
  1205. /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
  1206. } else {
  1207. Token *Toks =
  1208. (Token*) PP.getPreprocessorAllocator().Allocate(
  1209. sizeof(Token) * 2, llvm::alignOf<Token>());
  1210. Token &pragmaUnusedTok = Toks[0];
  1211. pragmaUnusedTok.startToken();
  1212. pragmaUnusedTok.setKind(tok::annot_pragma_weak);
  1213. pragmaUnusedTok.setLocation(WeakLoc);
  1214. pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
  1215. Toks[1] = WeakName;
  1216. PP.EnterTokenStream(Toks, 2,
  1217. /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
  1218. }
  1219. }
  1220. // #pragma redefine_extname identifier identifier
  1221. void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
  1222. PragmaIntroducerKind Introducer,
  1223. Token &RedefToken) {
  1224. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1225. SourceLocation RedefLoc = RedefToken.getLocation();
  1226. Token Tok;
  1227. PP.Lex(Tok);
  1228. if (Tok.isNot(tok::identifier)) {
  1229. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
  1230. "redefine_extname";
  1231. return;
  1232. }
  1233. Token RedefName = Tok;
  1234. PP.Lex(Tok);
  1235. if (Tok.isNot(tok::identifier)) {
  1236. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  1237. << "redefine_extname";
  1238. return;
  1239. }
  1240. Token AliasName = Tok;
  1241. PP.Lex(Tok);
  1242. if (Tok.isNot(tok::eod)) {
  1243. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
  1244. "redefine_extname";
  1245. return;
  1246. }
  1247. Token *Toks =
  1248. (Token*) PP.getPreprocessorAllocator().Allocate(
  1249. sizeof(Token) * 3, llvm::alignOf<Token>());
  1250. Token &pragmaRedefTok = Toks[0];
  1251. pragmaRedefTok.startToken();
  1252. pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
  1253. pragmaRedefTok.setLocation(RedefLoc);
  1254. pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
  1255. Toks[1] = RedefName;
  1256. Toks[2] = AliasName;
  1257. PP.EnterTokenStream(Toks, 3,
  1258. /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
  1259. }
  1260. void
  1261. PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
  1262. PragmaIntroducerKind Introducer,
  1263. Token &Tok) {
  1264. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1265. tok::OnOffSwitch OOS;
  1266. if (PP.LexOnOffSwitch(OOS))
  1267. return;
  1268. Token *Toks =
  1269. (Token*) PP.getPreprocessorAllocator().Allocate(
  1270. sizeof(Token) * 1, llvm::alignOf<Token>());
  1271. new (Toks) Token();
  1272. Toks[0].startToken();
  1273. Toks[0].setKind(tok::annot_pragma_fp_contract);
  1274. Toks[0].setLocation(Tok.getLocation());
  1275. Toks[0].setAnnotationEndLoc(Tok.getLocation());
  1276. Toks[0].setAnnotationValue(reinterpret_cast<void*>(
  1277. static_cast<uintptr_t>(OOS)));
  1278. PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
  1279. /*OwnsTokens=*/false);
  1280. }
  1281. void
  1282. PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
  1283. PragmaIntroducerKind Introducer,
  1284. Token &Tok) {
  1285. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1286. PP.LexUnexpandedToken(Tok);
  1287. if (Tok.isNot(tok::identifier)) {
  1288. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
  1289. "OPENCL";
  1290. return;
  1291. }
  1292. IdentifierInfo *ename = Tok.getIdentifierInfo();
  1293. SourceLocation NameLoc = Tok.getLocation();
  1294. PP.Lex(Tok);
  1295. if (Tok.isNot(tok::colon)) {
  1296. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
  1297. return;
  1298. }
  1299. PP.Lex(Tok);
  1300. if (Tok.isNot(tok::identifier)) {
  1301. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
  1302. return;
  1303. }
  1304. IdentifierInfo *op = Tok.getIdentifierInfo();
  1305. unsigned state;
  1306. if (op->isStr("enable")) {
  1307. state = 1;
  1308. } else if (op->isStr("disable")) {
  1309. state = 0;
  1310. } else {
  1311. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
  1312. return;
  1313. }
  1314. SourceLocation StateLoc = Tok.getLocation();
  1315. PP.Lex(Tok);
  1316. if (Tok.isNot(tok::eod)) {
  1317. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
  1318. "OPENCL EXTENSION";
  1319. return;
  1320. }
  1321. OpenCLExtData data(ename, state);
  1322. Token *Toks =
  1323. (Token*) PP.getPreprocessorAllocator().Allocate(
  1324. sizeof(Token) * 1, llvm::alignOf<Token>());
  1325. new (Toks) Token();
  1326. Toks[0].startToken();
  1327. Toks[0].setKind(tok::annot_pragma_opencl_extension);
  1328. Toks[0].setLocation(NameLoc);
  1329. Toks[0].setAnnotationValue(data.getOpaqueValue());
  1330. Toks[0].setAnnotationEndLoc(StateLoc);
  1331. PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
  1332. /*OwnsTokens=*/false);
  1333. if (PP.getPPCallbacks())
  1334. PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
  1335. StateLoc, state);
  1336. }
  1337. /// \brief Handle '#pragma omp ...' when OpenMP is disabled.
  1338. ///
  1339. void
  1340. PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
  1341. PragmaIntroducerKind Introducer,
  1342. Token &FirstTok) {
  1343. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1344. if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
  1345. FirstTok.getLocation())) {
  1346. PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
  1347. PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
  1348. diag::Severity::Ignored, SourceLocation());
  1349. }
  1350. PP.DiscardUntilEndOfDirective();
  1351. }
  1352. /// \brief Handle '#pragma omp ...' when OpenMP is enabled.
  1353. ///
  1354. void
  1355. PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
  1356. PragmaIntroducerKind Introducer,
  1357. Token &FirstTok) {
  1358. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1359. SmallVector<Token, 16> Pragma;
  1360. Token Tok;
  1361. Tok.startToken();
  1362. Tok.setKind(tok::annot_pragma_openmp);
  1363. Tok.setLocation(FirstTok.getLocation());
  1364. while (Tok.isNot(tok::eod)) {
  1365. Pragma.push_back(Tok);
  1366. PP.Lex(Tok);
  1367. }
  1368. SourceLocation EodLoc = Tok.getLocation();
  1369. Tok.startToken();
  1370. Tok.setKind(tok::annot_pragma_openmp_end);
  1371. Tok.setLocation(EodLoc);
  1372. Pragma.push_back(Tok);
  1373. Token *Toks = new Token[Pragma.size()];
  1374. std::copy(Pragma.begin(), Pragma.end(), Toks);
  1375. PP.EnterTokenStream(Toks, Pragma.size(),
  1376. /*DisableMacroExpansion=*/false, /*OwnsTokens=*/true);
  1377. }
  1378. /// \brief Handle '#pragma pointers_to_members'
  1379. // The grammar for this pragma is as follows:
  1380. //
  1381. // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
  1382. //
  1383. // #pragma pointers_to_members '(' 'best_case' ')'
  1384. // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
  1385. // #pragma pointers_to_members '(' inheritance-model ')'
  1386. void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
  1387. PragmaIntroducerKind Introducer,
  1388. Token &Tok) {
  1389. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1390. SourceLocation PointersToMembersLoc = Tok.getLocation();
  1391. PP.Lex(Tok);
  1392. if (Tok.isNot(tok::l_paren)) {
  1393. PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
  1394. << "pointers_to_members";
  1395. return;
  1396. }
  1397. PP.Lex(Tok);
  1398. const IdentifierInfo *Arg = Tok.getIdentifierInfo();
  1399. if (!Arg) {
  1400. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
  1401. << "pointers_to_members";
  1402. return;
  1403. }
  1404. PP.Lex(Tok);
  1405. LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
  1406. if (Arg->isStr("best_case")) {
  1407. RepresentationMethod = LangOptions::PPTMK_BestCase;
  1408. } else {
  1409. if (Arg->isStr("full_generality")) {
  1410. if (Tok.is(tok::comma)) {
  1411. PP.Lex(Tok);
  1412. Arg = Tok.getIdentifierInfo();
  1413. if (!Arg) {
  1414. PP.Diag(Tok.getLocation(),
  1415. diag::err_pragma_pointers_to_members_unknown_kind)
  1416. << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
  1417. return;
  1418. }
  1419. PP.Lex(Tok);
  1420. } else if (Tok.is(tok::r_paren)) {
  1421. // #pragma pointers_to_members(full_generality) implicitly specifies
  1422. // virtual_inheritance.
  1423. Arg = nullptr;
  1424. RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
  1425. } else {
  1426. PP.Diag(Tok.getLocation(), diag::err_expected_punc)
  1427. << "full_generality";
  1428. return;
  1429. }
  1430. }
  1431. if (Arg) {
  1432. if (Arg->isStr("single_inheritance")) {
  1433. RepresentationMethod =
  1434. LangOptions::PPTMK_FullGeneralitySingleInheritance;
  1435. } else if (Arg->isStr("multiple_inheritance")) {
  1436. RepresentationMethod =
  1437. LangOptions::PPTMK_FullGeneralityMultipleInheritance;
  1438. } else if (Arg->isStr("virtual_inheritance")) {
  1439. RepresentationMethod =
  1440. LangOptions::PPTMK_FullGeneralityVirtualInheritance;
  1441. } else {
  1442. PP.Diag(Tok.getLocation(),
  1443. diag::err_pragma_pointers_to_members_unknown_kind)
  1444. << Arg << /*HasPointerDeclaration*/ 1;
  1445. return;
  1446. }
  1447. }
  1448. }
  1449. if (Tok.isNot(tok::r_paren)) {
  1450. PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
  1451. << (Arg ? Arg->getName() : "full_generality");
  1452. return;
  1453. }
  1454. SourceLocation EndLoc = Tok.getLocation();
  1455. PP.Lex(Tok);
  1456. if (Tok.isNot(tok::eod)) {
  1457. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1458. << "pointers_to_members";
  1459. return;
  1460. }
  1461. Token AnnotTok;
  1462. AnnotTok.startToken();
  1463. AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
  1464. AnnotTok.setLocation(PointersToMembersLoc);
  1465. AnnotTok.setAnnotationEndLoc(EndLoc);
  1466. AnnotTok.setAnnotationValue(
  1467. reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
  1468. PP.EnterToken(AnnotTok);
  1469. }
  1470. /// \brief Handle '#pragma vtordisp'
  1471. // The grammar for this pragma is as follows:
  1472. //
  1473. // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
  1474. //
  1475. // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
  1476. // #pragma vtordisp '(' 'pop' ')'
  1477. // #pragma vtordisp '(' ')'
  1478. void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
  1479. PragmaIntroducerKind Introducer,
  1480. Token &Tok) {
  1481. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1482. SourceLocation VtorDispLoc = Tok.getLocation();
  1483. PP.Lex(Tok);
  1484. if (Tok.isNot(tok::l_paren)) {
  1485. PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
  1486. return;
  1487. }
  1488. PP.Lex(Tok);
  1489. Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
  1490. const IdentifierInfo *II = Tok.getIdentifierInfo();
  1491. if (II) {
  1492. if (II->isStr("push")) {
  1493. // #pragma vtordisp(push, mode)
  1494. PP.Lex(Tok);
  1495. if (Tok.isNot(tok::comma)) {
  1496. PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
  1497. return;
  1498. }
  1499. PP.Lex(Tok);
  1500. Kind = Sema::PVDK_Push;
  1501. // not push, could be on/off
  1502. } else if (II->isStr("pop")) {
  1503. // #pragma vtordisp(pop)
  1504. PP.Lex(Tok);
  1505. Kind = Sema::PVDK_Pop;
  1506. }
  1507. // not push or pop, could be on/off
  1508. } else {
  1509. if (Tok.is(tok::r_paren)) {
  1510. // #pragma vtordisp()
  1511. Kind = Sema::PVDK_Reset;
  1512. }
  1513. }
  1514. uint64_t Value = 0;
  1515. if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
  1516. const IdentifierInfo *II = Tok.getIdentifierInfo();
  1517. if (II && II->isStr("off")) {
  1518. PP.Lex(Tok);
  1519. Value = 0;
  1520. } else if (II && II->isStr("on")) {
  1521. PP.Lex(Tok);
  1522. Value = 1;
  1523. } else if (Tok.is(tok::numeric_constant) &&
  1524. PP.parseSimpleIntegerLiteral(Tok, Value)) {
  1525. if (Value > 2) {
  1526. PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
  1527. << 0 << 2 << "vtordisp";
  1528. return;
  1529. }
  1530. } else {
  1531. PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
  1532. << "vtordisp";
  1533. return;
  1534. }
  1535. }
  1536. // Finish the pragma: ')' $
  1537. if (Tok.isNot(tok::r_paren)) {
  1538. PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
  1539. return;
  1540. }
  1541. SourceLocation EndLoc = Tok.getLocation();
  1542. PP.Lex(Tok);
  1543. if (Tok.isNot(tok::eod)) {
  1544. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1545. << "vtordisp";
  1546. return;
  1547. }
  1548. // Enter the annotation.
  1549. Token AnnotTok;
  1550. AnnotTok.startToken();
  1551. AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
  1552. AnnotTok.setLocation(VtorDispLoc);
  1553. AnnotTok.setAnnotationEndLoc(EndLoc);
  1554. // OACR error 6297
  1555. #pragma prefast(disable: __WARNING_RESULTOFSHIFTCASTTOLARGERSIZE, "valid Kind values will not overflow")
  1556. AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
  1557. static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
  1558. PP.EnterToken(AnnotTok);
  1559. }
  1560. /// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
  1561. /// an annotation token.
  1562. void PragmaMSPragma::HandlePragma(Preprocessor &PP,
  1563. PragmaIntroducerKind Introducer,
  1564. Token &Tok) {
  1565. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1566. Token EoF, AnnotTok;
  1567. EoF.startToken();
  1568. EoF.setKind(tok::eof);
  1569. AnnotTok.startToken();
  1570. AnnotTok.setKind(tok::annot_pragma_ms_pragma);
  1571. AnnotTok.setLocation(Tok.getLocation());
  1572. AnnotTok.setAnnotationEndLoc(Tok.getLocation());
  1573. SmallVector<Token, 8> TokenVector;
  1574. // Suck up all of the tokens before the eod.
  1575. for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
  1576. TokenVector.push_back(Tok);
  1577. AnnotTok.setAnnotationEndLoc(Tok.getLocation());
  1578. }
  1579. // Add a sentinal EoF token to the end of the list.
  1580. TokenVector.push_back(EoF);
  1581. // We must allocate this array with new because EnterTokenStream is going to
  1582. // delete it later.
  1583. Token *TokenArray = new Token[TokenVector.size()];
  1584. std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
  1585. auto Value = new (PP.getPreprocessorAllocator())
  1586. std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
  1587. AnnotTok.setAnnotationValue(Value);
  1588. PP.EnterToken(AnnotTok);
  1589. }
  1590. /// \brief Handle the Microsoft \#pragma detect_mismatch extension.
  1591. ///
  1592. /// The syntax is:
  1593. /// \code
  1594. /// #pragma detect_mismatch("name", "value")
  1595. /// \endcode
  1596. /// Where 'name' and 'value' are quoted strings. The values are embedded in
  1597. /// the object file and passed along to the linker. If the linker detects a
  1598. /// mismatch in the object file's values for the given name, a LNK2038 error
  1599. /// is emitted. See MSDN for more details.
  1600. void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
  1601. PragmaIntroducerKind Introducer,
  1602. Token &Tok) {
  1603. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1604. SourceLocation CommentLoc = Tok.getLocation();
  1605. PP.Lex(Tok);
  1606. if (Tok.isNot(tok::l_paren)) {
  1607. PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
  1608. return;
  1609. }
  1610. // Read the name to embed, which must be a string literal.
  1611. std::string NameString;
  1612. if (!PP.LexStringLiteral(Tok, NameString,
  1613. "pragma detect_mismatch",
  1614. /*MacroExpansion=*/true))
  1615. return;
  1616. // Read the comma followed by a second string literal.
  1617. std::string ValueString;
  1618. if (Tok.isNot(tok::comma)) {
  1619. PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
  1620. return;
  1621. }
  1622. if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
  1623. /*MacroExpansion=*/true))
  1624. return;
  1625. if (Tok.isNot(tok::r_paren)) {
  1626. PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
  1627. return;
  1628. }
  1629. PP.Lex(Tok); // Eat the r_paren.
  1630. if (Tok.isNot(tok::eod)) {
  1631. PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
  1632. return;
  1633. }
  1634. // If the pragma is lexically sound, notify any interested PPCallbacks.
  1635. if (PP.getPPCallbacks())
  1636. PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
  1637. ValueString);
  1638. Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
  1639. }
  1640. /// \brief Handle the microsoft \#pragma comment extension.
  1641. ///
  1642. /// The syntax is:
  1643. /// \code
  1644. /// #pragma comment(linker, "foo")
  1645. /// \endcode
  1646. /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
  1647. /// "foo" is a string, which is fully macro expanded, and permits string
  1648. /// concatenation, embedded escape characters etc. See MSDN for more details.
  1649. void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
  1650. PragmaIntroducerKind Introducer,
  1651. Token &Tok) {
  1652. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1653. SourceLocation CommentLoc = Tok.getLocation();
  1654. PP.Lex(Tok);
  1655. if (Tok.isNot(tok::l_paren)) {
  1656. PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
  1657. return;
  1658. }
  1659. // Read the identifier.
  1660. PP.Lex(Tok);
  1661. if (Tok.isNot(tok::identifier)) {
  1662. PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
  1663. return;
  1664. }
  1665. // Verify that this is one of the 5 whitelisted options.
  1666. IdentifierInfo *II = Tok.getIdentifierInfo();
  1667. Sema::PragmaMSCommentKind Kind =
  1668. llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
  1669. .Case("linker", Sema::PCK_Linker)
  1670. .Case("lib", Sema::PCK_Lib)
  1671. .Case("compiler", Sema::PCK_Compiler)
  1672. .Case("exestr", Sema::PCK_ExeStr)
  1673. .Case("user", Sema::PCK_User)
  1674. .Default(Sema::PCK_Unknown);
  1675. if (Kind == Sema::PCK_Unknown) {
  1676. PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
  1677. return;
  1678. }
  1679. // On PS4, issue a warning about any pragma comments other than
  1680. // #pragma comment lib.
  1681. if (PP.getTargetInfo().getTriple().isPS4() && Kind != Sema::PCK_Lib) {
  1682. PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
  1683. << II->getName();
  1684. return;
  1685. }
  1686. // Read the optional string if present.
  1687. PP.Lex(Tok);
  1688. std::string ArgumentString;
  1689. if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
  1690. "pragma comment",
  1691. /*MacroExpansion=*/true))
  1692. return;
  1693. // FIXME: warn that 'exestr' is deprecated.
  1694. // FIXME: If the kind is "compiler" warn if the string is present (it is
  1695. // ignored).
  1696. // The MSDN docs say that "lib" and "linker" require a string and have a short
  1697. // whitelist of linker options they support, but in practice MSVC doesn't
  1698. // issue a diagnostic. Therefore neither does clang.
  1699. if (Tok.isNot(tok::r_paren)) {
  1700. PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
  1701. return;
  1702. }
  1703. PP.Lex(Tok); // eat the r_paren.
  1704. if (Tok.isNot(tok::eod)) {
  1705. PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
  1706. return;
  1707. }
  1708. // If the pragma is lexically sound, notify any interested PPCallbacks.
  1709. if (PP.getPPCallbacks())
  1710. PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
  1711. Actions.ActOnPragmaMSComment(Kind, ArgumentString);
  1712. }
  1713. // #pragma clang optimize off
  1714. // #pragma clang optimize on
  1715. void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
  1716. PragmaIntroducerKind Introducer,
  1717. Token &FirstToken) {
  1718. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1719. Token Tok;
  1720. PP.Lex(Tok);
  1721. if (Tok.is(tok::eod)) {
  1722. PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
  1723. << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
  1724. return;
  1725. }
  1726. if (Tok.isNot(tok::identifier)) {
  1727. PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
  1728. << PP.getSpelling(Tok);
  1729. return;
  1730. }
  1731. const IdentifierInfo *II = Tok.getIdentifierInfo();
  1732. // The only accepted values are 'on' or 'off'.
  1733. bool IsOn = false;
  1734. if (II->isStr("on")) {
  1735. IsOn = true;
  1736. } else if (!II->isStr("off")) {
  1737. PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
  1738. << PP.getSpelling(Tok);
  1739. return;
  1740. }
  1741. PP.Lex(Tok);
  1742. if (Tok.isNot(tok::eod)) {
  1743. PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
  1744. << PP.getSpelling(Tok);
  1745. return;
  1746. }
  1747. Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
  1748. }
  1749. /// \brief Parses loop or unroll pragma hint value and fills in Info.
  1750. static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
  1751. Token Option, bool ValueInParens,
  1752. PragmaLoopHintInfo &Info) {
  1753. SmallVector<Token, 1> ValueList;
  1754. int OpenParens = ValueInParens ? 1 : 0;
  1755. // Read constant expression.
  1756. while (Tok.isNot(tok::eod)) {
  1757. if (Tok.is(tok::l_paren))
  1758. OpenParens++;
  1759. else if (Tok.is(tok::r_paren)) {
  1760. OpenParens--;
  1761. if (OpenParens == 0 && ValueInParens)
  1762. break;
  1763. }
  1764. ValueList.push_back(Tok);
  1765. PP.Lex(Tok);
  1766. }
  1767. if (ValueInParens) {
  1768. // Read ')'
  1769. if (Tok.isNot(tok::r_paren)) {
  1770. PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
  1771. return true;
  1772. }
  1773. PP.Lex(Tok);
  1774. }
  1775. Token EOFTok;
  1776. EOFTok.startToken();
  1777. EOFTok.setKind(tok::eof);
  1778. EOFTok.setLocation(Tok.getLocation());
  1779. ValueList.push_back(EOFTok); // Terminates expression for parsing.
  1780. Token *TokenArray = (Token *)PP.getPreprocessorAllocator().Allocate(
  1781. ValueList.size() * sizeof(Token), llvm::alignOf<Token>());
  1782. std::copy(ValueList.begin(), ValueList.end(), TokenArray);
  1783. Info.Toks = TokenArray;
  1784. Info.TokSize = ValueList.size();
  1785. Info.PragmaName = PragmaName;
  1786. Info.Option = Option;
  1787. return false;
  1788. }
  1789. /// \brief Handle the \#pragma clang loop directive.
  1790. /// #pragma clang 'loop' loop-hints
  1791. ///
  1792. /// loop-hints:
  1793. /// loop-hint loop-hints[opt]
  1794. ///
  1795. /// loop-hint:
  1796. /// 'vectorize' '(' loop-hint-keyword ')'
  1797. /// 'interleave' '(' loop-hint-keyword ')'
  1798. /// 'unroll' '(' unroll-hint-keyword ')'
  1799. /// 'vectorize_width' '(' loop-hint-value ')'
  1800. /// 'interleave_count' '(' loop-hint-value ')'
  1801. /// 'unroll_count' '(' loop-hint-value ')'
  1802. ///
  1803. /// loop-hint-keyword:
  1804. /// 'enable'
  1805. /// 'disable'
  1806. /// 'assume_safety'
  1807. ///
  1808. /// unroll-hint-keyword:
  1809. /// 'full'
  1810. /// 'disable'
  1811. ///
  1812. /// loop-hint-value:
  1813. /// constant-expression
  1814. ///
  1815. /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
  1816. /// try vectorizing the instructions of the loop it precedes. Specifying
  1817. /// interleave(enable) or interleave_count(_value_) instructs llvm to try
  1818. /// interleaving multiple iterations of the loop it precedes. The width of the
  1819. /// vector instructions is specified by vectorize_width() and the number of
  1820. /// interleaved loop iterations is specified by interleave_count(). Specifying a
  1821. /// value of 1 effectively disables vectorization/interleaving, even if it is
  1822. /// possible and profitable, and 0 is invalid. The loop vectorizer currently
  1823. /// only works on inner loops.
  1824. ///
  1825. /// The unroll and unroll_count directives control the concatenation
  1826. /// unroller. Specifying unroll(full) instructs llvm to try to
  1827. /// unroll the loop completely, and unroll(disable) disables unrolling
  1828. /// for the loop. Specifying unroll_count(_value_) instructs llvm to
  1829. /// try to unroll the loop the number of times indicated by the value.
  1830. void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
  1831. PragmaIntroducerKind Introducer,
  1832. Token &Tok) {
  1833. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1834. // Incoming token is "loop" from "#pragma clang loop".
  1835. Token PragmaName = Tok;
  1836. SmallVector<Token, 1> TokenList;
  1837. // Lex the optimization option and verify it is an identifier.
  1838. PP.Lex(Tok);
  1839. if (Tok.isNot(tok::identifier)) {
  1840. PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
  1841. << /*MissingOption=*/true << "";
  1842. return;
  1843. }
  1844. while (Tok.is(tok::identifier)) {
  1845. Token Option = Tok;
  1846. IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
  1847. bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
  1848. .Case("vectorize", true)
  1849. .Case("interleave", true)
  1850. .Case("unroll", true)
  1851. .Case("vectorize_width", true)
  1852. .Case("interleave_count", true)
  1853. .Case("unroll_count", true)
  1854. .Default(false);
  1855. if (!OptionValid) {
  1856. PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
  1857. << /*MissingOption=*/false << OptionInfo;
  1858. return;
  1859. }
  1860. PP.Lex(Tok);
  1861. // Read '('
  1862. if (Tok.isNot(tok::l_paren)) {
  1863. PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
  1864. return;
  1865. }
  1866. PP.Lex(Tok);
  1867. auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
  1868. if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
  1869. *Info))
  1870. return;
  1871. // Generate the loop hint token.
  1872. Token LoopHintTok;
  1873. LoopHintTok.startToken();
  1874. LoopHintTok.setKind(tok::annot_pragma_loop_hint);
  1875. LoopHintTok.setLocation(PragmaName.getLocation());
  1876. LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
  1877. LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
  1878. TokenList.push_back(LoopHintTok);
  1879. }
  1880. if (Tok.isNot(tok::eod)) {
  1881. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1882. << "clang loop";
  1883. return;
  1884. }
  1885. Token *TokenArray = new Token[TokenList.size()];
  1886. std::copy(TokenList.begin(), TokenList.end(), TokenArray);
  1887. PP.EnterTokenStream(TokenArray, TokenList.size(),
  1888. /*DisableMacroExpansion=*/false,
  1889. /*OwnsTokens=*/true);
  1890. }
  1891. /// \brief Handle the loop unroll optimization pragmas.
  1892. /// #pragma unroll
  1893. /// #pragma unroll unroll-hint-value
  1894. /// #pragma unroll '(' unroll-hint-value ')'
  1895. /// #pragma nounroll
  1896. ///
  1897. /// unroll-hint-value:
  1898. /// constant-expression
  1899. ///
  1900. /// Loop unrolling hints can be specified with '#pragma unroll' or
  1901. /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
  1902. /// contained in parentheses. With no argument the directive instructs llvm to
  1903. /// try to unroll the loop completely. A positive integer argument can be
  1904. /// specified to indicate the number of times the loop should be unrolled. To
  1905. /// maximize compatibility with other compilers the unroll count argument can be
  1906. /// specified with or without parentheses. Specifying, '#pragma nounroll'
  1907. /// disables unrolling of the loop.
  1908. void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
  1909. PragmaIntroducerKind Introducer,
  1910. Token &Tok) {
  1911. assert(!PP.getLangOpts().HLSL && "not supported in HLSL - unreachable"); // HLSL Change
  1912. // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
  1913. // "#pragma nounroll".
  1914. Token PragmaName = Tok;
  1915. PP.Lex(Tok);
  1916. auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
  1917. if (Tok.is(tok::eod)) {
  1918. // nounroll or unroll pragma without an argument.
  1919. Info->PragmaName = PragmaName;
  1920. Info->Option.startToken();
  1921. } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
  1922. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1923. << "nounroll";
  1924. return;
  1925. } else {
  1926. // Unroll pragma with an argument: "#pragma unroll N" or
  1927. // "#pragma unroll(N)".
  1928. // Read '(' if it exists.
  1929. bool ValueInParens = Tok.is(tok::l_paren);
  1930. if (ValueInParens)
  1931. PP.Lex(Tok);
  1932. Token Option;
  1933. Option.startToken();
  1934. if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
  1935. return;
  1936. // In CUDA, the argument to '#pragma unroll' should not be contained in
  1937. // parentheses.
  1938. if (PP.getLangOpts().CUDA && ValueInParens)
  1939. PP.Diag(Info->Toks[0].getLocation(),
  1940. diag::warn_pragma_unroll_cuda_value_in_parens);
  1941. if (Tok.isNot(tok::eod)) {
  1942. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
  1943. << "unroll";
  1944. return;
  1945. }
  1946. }
  1947. // Generate the hint token.
  1948. Token *TokenArray = new Token[1];
  1949. TokenArray[0].startToken();
  1950. TokenArray[0].setKind(tok::annot_pragma_loop_hint);
  1951. TokenArray[0].setLocation(PragmaName.getLocation());
  1952. TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
  1953. TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
  1954. PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false,
  1955. /*OwnsTokens=*/true);
  1956. }
  1957. // HLSL Change Begin - pack_matrix
  1958. /// \brief Handle the pack_matrix pragmas.
  1959. /// #pragma pack_matrix(row_major)
  1960. /// #pragma pack_matrix(column_major)
  1961. ///
  1962. void PragmaPackMatrixHandler::HandlePragma(Preprocessor &PP,
  1963. PragmaIntroducerKind Introducer,
  1964. Token &Tok) {
  1965. assert(PP.getLangOpts().HLSL && "only supported in HLSL");
  1966. Token PragmaName = Tok;
  1967. PP.Lex(Tok);
  1968. if (!Tok.is(tok::l_paren)) {
  1969. PP.Diag(Tok, diag::err_expected) << tok::l_brace;
  1970. return;
  1971. }
  1972. PP.Lex(Tok);
  1973. Token PragmaArg = Tok;
  1974. bool bRowMajor = false;
  1975. if (Tok.is(tok::kw_row_major)) {
  1976. bRowMajor = true;
  1977. }
  1978. else if (Tok.isNot(tok::kw_column_major)) {
  1979. PP.Diag(Tok.getLocation(), diag::err_pragma_invalid_keyword);
  1980. return;
  1981. }
  1982. // Make sure pragma finish correctly.
  1983. PP.Lex(Tok);
  1984. if (Tok.isNot(tok::r_paren)) {
  1985. PP.Diag(Tok, diag::err_expected) << tok::r_brace;
  1986. return;
  1987. }
  1988. PP.Lex(Tok);
  1989. if (Tok.isNot(tok::eod)) {
  1990. PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol);
  1991. return;
  1992. }
  1993. // Note: to make things easy, pack_matrix will modify ast type directly in
  1994. // Sema::TransferUnusualAttributes.
  1995. // Another solution is create ast node for pack_matrix, and take care it at
  1996. // clang codegen.
  1997. Actions.ActOnPragmaPackMatrix(bRowMajor, PragmaArg.getLocation());
  1998. }
  1999. // HLSL Change End.