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