ParsePragma.cpp 75 KB

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