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