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