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