clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ParsePragma.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libclangParse/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libclangParse/../../../llvm/clang/include -I /usr/src/gnu/usr.bin/clang/libclangParse/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libclangParse/../include -I /usr/src/gnu/usr.bin/clang/libclangParse/obj -I /usr/src/gnu/usr.bin/clang/libclangParse/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libclangParse/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libclangParse/../../../llvm/clang/lib/Parse/ParsePragma.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/AST/ASTContext.h" |
14 | #include "clang/Basic/PragmaKinds.h" |
15 | #include "clang/Basic/TargetInfo.h" |
16 | #include "clang/Lex/Preprocessor.h" |
17 | #include "clang/Lex/Token.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/ArrayRef.h" |
24 | #include "llvm/ADT/StringSwitch.h" |
25 | using namespace clang; |
26 | |
27 | namespace { |
28 | |
29 | struct PragmaAlignHandler : public PragmaHandler { |
30 | explicit PragmaAlignHandler() : PragmaHandler("align") {} |
31 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
32 | Token &FirstToken) override; |
33 | }; |
34 | |
35 | struct PragmaGCCVisibilityHandler : public PragmaHandler { |
36 | explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {} |
37 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
38 | Token &FirstToken) override; |
39 | }; |
40 | |
41 | struct PragmaOptionsHandler : public PragmaHandler { |
42 | explicit PragmaOptionsHandler() : PragmaHandler("options") {} |
43 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
44 | Token &FirstToken) override; |
45 | }; |
46 | |
47 | struct PragmaPackHandler : public PragmaHandler { |
48 | explicit PragmaPackHandler() : PragmaHandler("pack") {} |
49 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
50 | Token &FirstToken) override; |
51 | }; |
52 | |
53 | struct PragmaClangSectionHandler : public PragmaHandler { |
54 | explicit PragmaClangSectionHandler(Sema &S) |
55 | : PragmaHandler("section"), Actions(S) {} |
56 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
57 | Token &FirstToken) override; |
58 | |
59 | private: |
60 | Sema &Actions; |
61 | }; |
62 | |
63 | struct PragmaMSStructHandler : public PragmaHandler { |
64 | explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {} |
65 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
66 | Token &FirstToken) override; |
67 | }; |
68 | |
69 | struct PragmaUnusedHandler : public PragmaHandler { |
70 | PragmaUnusedHandler() : PragmaHandler("unused") {} |
71 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
72 | Token &FirstToken) override; |
73 | }; |
74 | |
75 | struct PragmaWeakHandler : public PragmaHandler { |
76 | explicit PragmaWeakHandler() : PragmaHandler("weak") {} |
77 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
78 | Token &FirstToken) override; |
79 | }; |
80 | |
81 | struct PragmaRedefineExtnameHandler : public PragmaHandler { |
82 | explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {} |
83 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
84 | Token &FirstToken) override; |
85 | }; |
86 | |
87 | struct PragmaOpenCLExtensionHandler : public PragmaHandler { |
88 | PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {} |
89 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
90 | Token &FirstToken) override; |
91 | }; |
92 | |
93 | |
94 | struct PragmaFPContractHandler : public PragmaHandler { |
95 | PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {} |
96 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
97 | Token &FirstToken) override; |
98 | }; |
99 | |
100 | |
101 | |
102 | |
103 | struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { |
104 | PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {} |
105 | |
106 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
107 | Token &Tok) override { |
108 | Token PragmaName = Tok; |
109 | if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) { |
110 | PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored) |
111 | << PragmaName.getIdentifierInfo()->getName(); |
112 | return; |
113 | } |
114 | tok::OnOffSwitch OOS; |
115 | if (PP.LexOnOffSwitch(OOS)) |
116 | return; |
117 | |
118 | MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), |
119 | 1); |
120 | Toks[0].startToken(); |
121 | Toks[0].setKind(tok::annot_pragma_fenv_access); |
122 | Toks[0].setLocation(Tok.getLocation()); |
123 | Toks[0].setAnnotationEndLoc(Tok.getLocation()); |
124 | Toks[0].setAnnotationValue(reinterpret_cast<void*>( |
125 | static_cast<uintptr_t>(OOS))); |
126 | PP.EnterTokenStream(Toks, true, |
127 | false); |
128 | } |
129 | }; |
130 | |
131 | |
132 | struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { |
133 | PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {} |
134 | |
135 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
136 | Token &Tok) override { |
137 | tok::OnOffSwitch OOS; |
138 | PP.LexOnOffSwitch(OOS); |
139 | } |
140 | }; |
141 | |
142 | |
143 | struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler { |
144 | PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {} |
145 | |
146 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
147 | Token &Tok) override; |
148 | }; |
149 | |
150 | |
151 | struct PragmaSTDC_UnknownHandler : public PragmaHandler { |
152 | PragmaSTDC_UnknownHandler() = default; |
153 | |
154 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
155 | Token &UnknownTok) override { |
156 | |
157 | PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored); |
158 | } |
159 | }; |
160 | |
161 | struct PragmaFPHandler : public PragmaHandler { |
162 | PragmaFPHandler() : PragmaHandler("fp") {} |
163 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
164 | Token &FirstToken) override; |
165 | }; |
166 | |
167 | struct PragmaNoOpenMPHandler : public PragmaHandler { |
168 | PragmaNoOpenMPHandler() : PragmaHandler("omp") { } |
169 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
170 | Token &FirstToken) override; |
171 | }; |
172 | |
173 | struct PragmaOpenMPHandler : public PragmaHandler { |
174 | PragmaOpenMPHandler() : PragmaHandler("omp") { } |
175 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
176 | Token &FirstToken) override; |
177 | }; |
178 | |
179 | |
180 | struct PragmaCommentHandler : public PragmaHandler { |
181 | PragmaCommentHandler(Sema &Actions) |
182 | : PragmaHandler("comment"), Actions(Actions) {} |
183 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
184 | Token &FirstToken) override; |
185 | |
186 | private: |
187 | Sema &Actions; |
188 | }; |
189 | |
190 | struct PragmaDetectMismatchHandler : public PragmaHandler { |
191 | PragmaDetectMismatchHandler(Sema &Actions) |
192 | : PragmaHandler("detect_mismatch"), Actions(Actions) {} |
193 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
194 | Token &FirstToken) override; |
195 | |
196 | private: |
197 | Sema &Actions; |
198 | }; |
199 | |
200 | struct PragmaFloatControlHandler : public PragmaHandler { |
201 | PragmaFloatControlHandler(Sema &Actions) |
202 | : PragmaHandler("float_control") {} |
203 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
204 | Token &FirstToken) override; |
205 | }; |
206 | |
207 | struct PragmaMSPointersToMembers : public PragmaHandler { |
208 | explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {} |
209 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
210 | Token &FirstToken) override; |
211 | }; |
212 | |
213 | struct PragmaMSVtorDisp : public PragmaHandler { |
214 | explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {} |
215 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
216 | Token &FirstToken) override; |
217 | }; |
218 | |
219 | struct PragmaMSPragma : public PragmaHandler { |
220 | explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {} |
221 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
222 | Token &FirstToken) override; |
223 | }; |
224 | |
225 | |
226 | struct PragmaOptimizeHandler : public PragmaHandler { |
227 | PragmaOptimizeHandler(Sema &S) |
228 | : PragmaHandler("optimize"), Actions(S) {} |
229 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
230 | Token &FirstToken) override; |
231 | |
232 | private: |
233 | Sema &Actions; |
234 | }; |
235 | |
236 | struct PragmaLoopHintHandler : public PragmaHandler { |
237 | PragmaLoopHintHandler() : PragmaHandler("loop") {} |
238 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
239 | Token &FirstToken) override; |
240 | }; |
241 | |
242 | struct PragmaUnrollHintHandler : public PragmaHandler { |
243 | PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {} |
244 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
245 | Token &FirstToken) override; |
246 | }; |
247 | |
248 | struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler { |
249 | PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {} |
250 | }; |
251 | |
252 | struct PragmaMSIntrinsicHandler : public PragmaHandler { |
253 | PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {} |
254 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
255 | Token &FirstToken) override; |
256 | }; |
257 | |
258 | struct PragmaMSOptimizeHandler : public PragmaHandler { |
259 | PragmaMSOptimizeHandler() : PragmaHandler("optimize") {} |
260 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
261 | Token &FirstToken) override; |
262 | }; |
263 | |
264 | struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler { |
265 | PragmaForceCUDAHostDeviceHandler(Sema &Actions) |
266 | : PragmaHandler("force_cuda_host_device"), Actions(Actions) {} |
267 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
268 | Token &FirstToken) override; |
269 | |
270 | private: |
271 | Sema &Actions; |
272 | }; |
273 | |
274 | |
275 | struct PragmaAttributeHandler : public PragmaHandler { |
276 | PragmaAttributeHandler(AttributeFactory &AttrFactory) |
277 | : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {} |
278 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
279 | Token &FirstToken) override; |
280 | |
281 | |
282 | ParsedAttributes AttributesForPragmaAttribute; |
283 | }; |
284 | |
285 | struct PragmaMaxTokensHereHandler : public PragmaHandler { |
286 | PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {} |
287 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
288 | Token &FirstToken) override; |
289 | }; |
290 | |
291 | struct PragmaMaxTokensTotalHandler : public PragmaHandler { |
292 | PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {} |
293 | void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, |
294 | Token &FirstToken) override; |
295 | }; |
296 | |
297 | void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) { |
298 | for (auto &T : Toks) |
299 | T.setFlag(clang::Token::IsReinjected); |
300 | } |
301 | } |
302 | |
303 | void Parser::initializePragmaHandlers() { |
304 | AlignHandler = std::make_unique<PragmaAlignHandler>(); |
305 | PP.AddPragmaHandler(AlignHandler.get()); |
306 | |
307 | GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>(); |
308 | PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get()); |
309 | |
310 | OptionsHandler = std::make_unique<PragmaOptionsHandler>(); |
311 | PP.AddPragmaHandler(OptionsHandler.get()); |
312 | |
313 | PackHandler = std::make_unique<PragmaPackHandler>(); |
314 | PP.AddPragmaHandler(PackHandler.get()); |
315 | |
316 | MSStructHandler = std::make_unique<PragmaMSStructHandler>(); |
317 | PP.AddPragmaHandler(MSStructHandler.get()); |
318 | |
319 | UnusedHandler = std::make_unique<PragmaUnusedHandler>(); |
320 | PP.AddPragmaHandler(UnusedHandler.get()); |
321 | |
322 | WeakHandler = std::make_unique<PragmaWeakHandler>(); |
323 | PP.AddPragmaHandler(WeakHandler.get()); |
324 | |
325 | RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>(); |
326 | PP.AddPragmaHandler(RedefineExtnameHandler.get()); |
327 | |
328 | FPContractHandler = std::make_unique<PragmaFPContractHandler>(); |
329 | PP.AddPragmaHandler("STDC", FPContractHandler.get()); |
330 | |
331 | STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>(); |
332 | PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get()); |
333 | |
334 | STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>(); |
335 | PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get()); |
336 | |
337 | STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>(); |
338 | PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get()); |
339 | |
340 | STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>(); |
341 | PP.AddPragmaHandler("STDC", STDCUnknownHandler.get()); |
342 | |
343 | PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions); |
344 | PP.AddPragmaHandler("clang", PCSectionHandler.get()); |
345 | |
346 | if (getLangOpts().OpenCL) { |
347 | OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>(); |
348 | PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); |
349 | |
350 | PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); |
351 | } |
352 | if (getLangOpts().OpenMP) |
353 | OpenMPHandler = std::make_unique<PragmaOpenMPHandler>(); |
354 | else |
355 | OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>(); |
356 | PP.AddPragmaHandler(OpenMPHandler.get()); |
357 | |
358 | if (getLangOpts().MicrosoftExt || |
359 | getTargetInfo().getTriple().isOSBinFormatELF()) { |
360 | MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions); |
361 | PP.AddPragmaHandler(MSCommentHandler.get()); |
362 | } |
363 | |
364 | FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions); |
365 | PP.AddPragmaHandler(FloatControlHandler.get()); |
366 | if (getLangOpts().MicrosoftExt) { |
367 | MSDetectMismatchHandler = |
368 | std::make_unique<PragmaDetectMismatchHandler>(Actions); |
369 | PP.AddPragmaHandler(MSDetectMismatchHandler.get()); |
370 | MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>(); |
371 | PP.AddPragmaHandler(MSPointersToMembers.get()); |
372 | MSVtorDisp = std::make_unique<PragmaMSVtorDisp>(); |
373 | PP.AddPragmaHandler(MSVtorDisp.get()); |
374 | MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg"); |
375 | PP.AddPragmaHandler(MSInitSeg.get()); |
376 | MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg"); |
377 | PP.AddPragmaHandler(MSDataSeg.get()); |
378 | MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg"); |
379 | PP.AddPragmaHandler(MSBSSSeg.get()); |
380 | MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg"); |
381 | PP.AddPragmaHandler(MSConstSeg.get()); |
382 | MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg"); |
383 | PP.AddPragmaHandler(MSCodeSeg.get()); |
384 | MSSection = std::make_unique<PragmaMSPragma>("section"); |
385 | PP.AddPragmaHandler(MSSection.get()); |
386 | MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>(); |
387 | PP.AddPragmaHandler(MSRuntimeChecks.get()); |
388 | MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>(); |
389 | PP.AddPragmaHandler(MSIntrinsic.get()); |
390 | MSOptimize = std::make_unique<PragmaMSOptimizeHandler>(); |
391 | PP.AddPragmaHandler(MSOptimize.get()); |
392 | } |
393 | |
394 | if (getLangOpts().CUDA) { |
395 | CUDAForceHostDeviceHandler = |
396 | std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions); |
397 | PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get()); |
398 | } |
399 | |
400 | OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions); |
401 | PP.AddPragmaHandler("clang", OptimizeHandler.get()); |
402 | |
403 | LoopHintHandler = std::make_unique<PragmaLoopHintHandler>(); |
404 | PP.AddPragmaHandler("clang", LoopHintHandler.get()); |
405 | |
406 | UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll"); |
407 | PP.AddPragmaHandler(UnrollHintHandler.get()); |
408 | PP.AddPragmaHandler("GCC", UnrollHintHandler.get()); |
409 | |
410 | NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll"); |
411 | PP.AddPragmaHandler(NoUnrollHintHandler.get()); |
412 | PP.AddPragmaHandler("GCC", NoUnrollHintHandler.get()); |
413 | |
414 | UnrollAndJamHintHandler = |
415 | std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam"); |
416 | PP.AddPragmaHandler(UnrollAndJamHintHandler.get()); |
417 | |
418 | NoUnrollAndJamHintHandler = |
419 | std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam"); |
420 | PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get()); |
421 | |
422 | FPHandler = std::make_unique<PragmaFPHandler>(); |
423 | PP.AddPragmaHandler("clang", FPHandler.get()); |
424 | |
425 | AttributePragmaHandler = |
426 | std::make_unique<PragmaAttributeHandler>(AttrFactory); |
427 | PP.AddPragmaHandler("clang", AttributePragmaHandler.get()); |
428 | |
429 | MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>(); |
430 | PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get()); |
431 | |
432 | MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>(); |
433 | PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get()); |
434 | } |
435 | |
436 | void Parser::resetPragmaHandlers() { |
437 | |
438 | PP.RemovePragmaHandler(AlignHandler.get()); |
439 | AlignHandler.reset(); |
440 | PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get()); |
441 | GCCVisibilityHandler.reset(); |
442 | PP.RemovePragmaHandler(OptionsHandler.get()); |
443 | OptionsHandler.reset(); |
444 | PP.RemovePragmaHandler(PackHandler.get()); |
445 | PackHandler.reset(); |
446 | PP.RemovePragmaHandler(MSStructHandler.get()); |
447 | MSStructHandler.reset(); |
448 | PP.RemovePragmaHandler(UnusedHandler.get()); |
449 | UnusedHandler.reset(); |
450 | PP.RemovePragmaHandler(WeakHandler.get()); |
451 | WeakHandler.reset(); |
452 | PP.RemovePragmaHandler(RedefineExtnameHandler.get()); |
453 | RedefineExtnameHandler.reset(); |
454 | |
455 | if (getLangOpts().OpenCL) { |
456 | PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get()); |
457 | OpenCLExtensionHandler.reset(); |
458 | PP.RemovePragmaHandler("OPENCL", FPContractHandler.get()); |
459 | } |
460 | PP.RemovePragmaHandler(OpenMPHandler.get()); |
461 | OpenMPHandler.reset(); |
462 | |
463 | if (getLangOpts().MicrosoftExt || |
464 | getTargetInfo().getTriple().isOSBinFormatELF()) { |
465 | PP.RemovePragmaHandler(MSCommentHandler.get()); |
466 | MSCommentHandler.reset(); |
467 | } |
468 | |
469 | PP.RemovePragmaHandler("clang", PCSectionHandler.get()); |
470 | PCSectionHandler.reset(); |
471 | |
472 | PP.RemovePragmaHandler(FloatControlHandler.get()); |
473 | FloatControlHandler.reset(); |
474 | if (getLangOpts().MicrosoftExt) { |
475 | PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); |
476 | MSDetectMismatchHandler.reset(); |
477 | PP.RemovePragmaHandler(MSPointersToMembers.get()); |
478 | MSPointersToMembers.reset(); |
479 | PP.RemovePragmaHandler(MSVtorDisp.get()); |
480 | MSVtorDisp.reset(); |
481 | PP.RemovePragmaHandler(MSInitSeg.get()); |
482 | MSInitSeg.reset(); |
483 | PP.RemovePragmaHandler(MSDataSeg.get()); |
484 | MSDataSeg.reset(); |
485 | PP.RemovePragmaHandler(MSBSSSeg.get()); |
486 | MSBSSSeg.reset(); |
487 | PP.RemovePragmaHandler(MSConstSeg.get()); |
488 | MSConstSeg.reset(); |
489 | PP.RemovePragmaHandler(MSCodeSeg.get()); |
490 | MSCodeSeg.reset(); |
491 | PP.RemovePragmaHandler(MSSection.get()); |
492 | MSSection.reset(); |
493 | PP.RemovePragmaHandler(MSRuntimeChecks.get()); |
494 | MSRuntimeChecks.reset(); |
495 | PP.RemovePragmaHandler(MSIntrinsic.get()); |
496 | MSIntrinsic.reset(); |
497 | PP.RemovePragmaHandler(MSOptimize.get()); |
498 | MSOptimize.reset(); |
499 | } |
500 | |
501 | if (getLangOpts().CUDA) { |
502 | PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get()); |
503 | CUDAForceHostDeviceHandler.reset(); |
504 | } |
505 | |
506 | PP.RemovePragmaHandler("STDC", FPContractHandler.get()); |
507 | FPContractHandler.reset(); |
508 | |
509 | PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get()); |
510 | STDCFenvAccessHandler.reset(); |
511 | |
512 | PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get()); |
513 | STDCFenvRoundHandler.reset(); |
514 | |
515 | PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get()); |
516 | STDCCXLIMITHandler.reset(); |
517 | |
518 | PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get()); |
519 | STDCUnknownHandler.reset(); |
520 | |
521 | PP.RemovePragmaHandler("clang", OptimizeHandler.get()); |
522 | OptimizeHandler.reset(); |
523 | |
524 | PP.RemovePragmaHandler("clang", LoopHintHandler.get()); |
525 | LoopHintHandler.reset(); |
526 | |
527 | PP.RemovePragmaHandler(UnrollHintHandler.get()); |
528 | PP.RemovePragmaHandler("GCC", UnrollHintHandler.get()); |
529 | UnrollHintHandler.reset(); |
530 | |
531 | PP.RemovePragmaHandler(NoUnrollHintHandler.get()); |
532 | PP.RemovePragmaHandler("GCC", NoUnrollHintHandler.get()); |
533 | NoUnrollHintHandler.reset(); |
534 | |
535 | PP.RemovePragmaHandler(UnrollAndJamHintHandler.get()); |
536 | UnrollAndJamHintHandler.reset(); |
537 | |
538 | PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get()); |
539 | NoUnrollAndJamHintHandler.reset(); |
540 | |
541 | PP.RemovePragmaHandler("clang", FPHandler.get()); |
542 | FPHandler.reset(); |
543 | |
544 | PP.RemovePragmaHandler("clang", AttributePragmaHandler.get()); |
545 | AttributePragmaHandler.reset(); |
546 | |
547 | PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get()); |
548 | MaxTokensHerePragmaHandler.reset(); |
549 | |
550 | PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get()); |
551 | MaxTokensTotalPragmaHandler.reset(); |
552 | } |
553 | |
554 | |
555 | |
556 | |
557 | |
558 | |
559 | void Parser::HandlePragmaUnused() { |
560 | assert(Tok.is(tok::annot_pragma_unused)); |
561 | SourceLocation UnusedLoc = ConsumeAnnotationToken(); |
562 | Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc); |
563 | ConsumeToken(); |
564 | } |
565 | |
566 | void Parser::HandlePragmaVisibility() { |
567 | assert(Tok.is(tok::annot_pragma_vis)); |
568 | const IdentifierInfo *VisType = |
569 | static_cast<IdentifierInfo *>(Tok.getAnnotationValue()); |
570 | SourceLocation VisLoc = ConsumeAnnotationToken(); |
571 | Actions.ActOnPragmaVisibility(VisType, VisLoc); |
572 | } |
573 | |
574 | namespace { |
575 | struct PragmaPackInfo { |
576 | Sema::PragmaMsStackAction Action; |
577 | StringRef SlotLabel; |
578 | Token Alignment; |
579 | }; |
580 | } |
581 | |
582 | void Parser::HandlePragmaPack() { |
583 | assert(Tok.is(tok::annot_pragma_pack)); |
584 | PragmaPackInfo *Info = |
585 | static_cast<PragmaPackInfo *>(Tok.getAnnotationValue()); |
586 | SourceLocation PragmaLoc = Tok.getLocation(); |
587 | ExprResult Alignment; |
588 | if (Info->Alignment.is(tok::numeric_constant)) { |
589 | Alignment = Actions.ActOnNumericConstant(Info->Alignment); |
590 | if (Alignment.isInvalid()) { |
591 | ConsumeAnnotationToken(); |
592 | return; |
593 | } |
594 | } |
595 | Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel, |
596 | Alignment.get()); |
597 | |
598 | |
599 | ConsumeAnnotationToken(); |
600 | } |
601 | |
602 | void Parser::HandlePragmaMSStruct() { |
603 | assert(Tok.is(tok::annot_pragma_msstruct)); |
604 | PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>( |
605 | reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); |
606 | Actions.ActOnPragmaMSStruct(Kind); |
607 | ConsumeAnnotationToken(); |
608 | } |
609 | |
610 | void Parser::HandlePragmaAlign() { |
611 | assert(Tok.is(tok::annot_pragma_align)); |
612 | Sema::PragmaOptionsAlignKind Kind = |
613 | static_cast<Sema::PragmaOptionsAlignKind>( |
614 | reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); |
615 | Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation()); |
616 | |
617 | |
618 | ConsumeAnnotationToken(); |
619 | } |
620 | |
621 | void Parser::HandlePragmaDump() { |
622 | assert(Tok.is(tok::annot_pragma_dump)); |
623 | IdentifierInfo *II = |
624 | reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue()); |
625 | Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II); |
626 | ConsumeAnnotationToken(); |
627 | } |
628 | |
629 | void Parser::HandlePragmaWeak() { |
630 | assert(Tok.is(tok::annot_pragma_weak)); |
631 | SourceLocation PragmaLoc = ConsumeAnnotationToken(); |
632 | Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc, |
633 | Tok.getLocation()); |
634 | ConsumeToken(); |
635 | } |
636 | |
637 | void Parser::HandlePragmaWeakAlias() { |
638 | assert(Tok.is(tok::annot_pragma_weakalias)); |
639 | SourceLocation PragmaLoc = ConsumeAnnotationToken(); |
640 | IdentifierInfo *WeakName = Tok.getIdentifierInfo(); |
641 | SourceLocation WeakNameLoc = Tok.getLocation(); |
642 | ConsumeToken(); |
643 | IdentifierInfo *AliasName = Tok.getIdentifierInfo(); |
644 | SourceLocation AliasNameLoc = Tok.getLocation(); |
645 | ConsumeToken(); |
646 | Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc, |
647 | WeakNameLoc, AliasNameLoc); |
648 | |
649 | } |
650 | |
651 | void Parser::HandlePragmaRedefineExtname() { |
652 | assert(Tok.is(tok::annot_pragma_redefine_extname)); |
653 | SourceLocation RedefLoc = ConsumeAnnotationToken(); |
654 | IdentifierInfo *RedefName = Tok.getIdentifierInfo(); |
655 | SourceLocation RedefNameLoc = Tok.getLocation(); |
656 | ConsumeToken(); |
657 | IdentifierInfo *AliasName = Tok.getIdentifierInfo(); |
658 | SourceLocation AliasNameLoc = Tok.getLocation(); |
659 | ConsumeToken(); |
660 | Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc, |
661 | RedefNameLoc, AliasNameLoc); |
662 | } |
663 | |
664 | void Parser::HandlePragmaFPContract() { |
665 | assert(Tok.is(tok::annot_pragma_fp_contract)); |
666 | tok::OnOffSwitch OOS = |
667 | static_cast<tok::OnOffSwitch>( |
668 | reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); |
669 | |
670 | LangOptions::FPModeKind FPC; |
671 | switch (OOS) { |
672 | case tok::OOS_ON: |
673 | FPC = LangOptions::FPM_On; |
674 | break; |
675 | case tok::OOS_OFF: |
676 | FPC = LangOptions::FPM_Off; |
677 | break; |
678 | case tok::OOS_DEFAULT: |
679 | FPC = getLangOpts().getDefaultFPContractMode(); |
680 | break; |
681 | } |
682 | |
683 | SourceLocation PragmaLoc = ConsumeAnnotationToken(); |
684 | Actions.ActOnPragmaFPContract(PragmaLoc, FPC); |
685 | } |
686 | |
687 | void Parser::HandlePragmaFloatControl() { |
688 | assert(Tok.is(tok::annot_pragma_float_control)); |
689 | |
690 | |
691 | |
692 | |
693 | |
694 | |
695 | uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()); |
696 | Sema::PragmaMsStackAction Action = |
697 | static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF); |
698 | PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF); |
699 | SourceLocation PragmaLoc = ConsumeAnnotationToken(); |
700 | Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind); |
701 | } |
702 | |
703 | void Parser::HandlePragmaFEnvAccess() { |
704 | assert(Tok.is(tok::annot_pragma_fenv_access)); |
705 | tok::OnOffSwitch OOS = |
706 | static_cast<tok::OnOffSwitch>( |
707 | reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); |
708 | |
709 | bool IsEnabled; |
710 | switch (OOS) { |
711 | case tok::OOS_ON: |
712 | IsEnabled = true; |
713 | break; |
714 | case tok::OOS_OFF: |
715 | IsEnabled = false; |
716 | break; |
717 | case tok::OOS_DEFAULT: |
718 | IsEnabled = false; |
719 | break; |
720 | } |
721 | |
722 | SourceLocation PragmaLoc = ConsumeAnnotationToken(); |
723 | Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled); |
724 | } |
725 | |
726 | void Parser::HandlePragmaFEnvRound() { |
727 | assert(Tok.is(tok::annot_pragma_fenv_round)); |
728 | auto RM = static_cast<llvm::RoundingMode>( |
729 | reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); |
730 | |
731 | SourceLocation PragmaLoc = ConsumeAnnotationToken(); |
732 | Actions.setRoundingMode(PragmaLoc, RM); |
733 | } |
734 | |
735 | StmtResult Parser::HandlePragmaCaptured() |
736 | { |
737 | assert(Tok.is(tok::annot_pragma_captured)); |
738 | ConsumeAnnotationToken(); |
739 | |
740 | if (Tok.isNot(tok::l_brace)) { |
741 | PP.Diag(Tok, diag::err_expected) << tok::l_brace; |
742 | return StmtError(); |
743 | } |
744 | |
745 | SourceLocation Loc = Tok.getLocation(); |
746 | |
747 | ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope | |
748 | Scope::CompoundStmtScope); |
749 | Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default, |
750 | 1); |
751 | |
752 | StmtResult R = ParseCompoundStatement(); |
753 | CapturedRegionScope.Exit(); |
754 | |
755 | if (R.isInvalid()) { |
756 | Actions.ActOnCapturedRegionError(); |
757 | return StmtError(); |
758 | } |
759 | |
760 | return Actions.ActOnCapturedRegionEnd(R.get()); |
761 | } |
762 | |
763 | namespace { |
764 | enum OpenCLExtState : char { |
765 | Disable, Enable, Begin, End |
766 | }; |
767 | typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData; |
768 | } |
769 | |
770 | void Parser::HandlePragmaOpenCLExtension() { |
771 | assert(Tok.is(tok::annot_pragma_opencl_extension)); |
772 | OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue()); |
773 | auto State = Data->second; |
774 | auto Ident = Data->first; |
775 | SourceLocation NameLoc = Tok.getLocation(); |
776 | ConsumeAnnotationToken(); |
777 | |
778 | auto &Opt = Actions.getOpenCLOptions(); |
779 | auto Name = Ident->getName(); |
780 | |
781 | |
782 | |
783 | if (Name == "all") { |
784 | if (State == Disable) |
785 | Opt.disableAll(); |
786 | else |
787 | PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1; |
788 | } else if (State == Begin) { |
789 | if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) { |
790 | Opt.support(Name); |
791 | |
792 | |
793 | Opt.acceptsPragma(Name); |
794 | } |
795 | } else if (State == End) { |
796 | |
797 | |
798 | } else if (!Opt.isKnown(Name) || !Opt.isWithPragma(Name)) |
799 | PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident; |
800 | else if (Opt.isSupportedExtension(Name, getLangOpts())) |
801 | Opt.enable(Name, State == Enable); |
802 | else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts())) |
803 | PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident; |
804 | else |
805 | PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident; |
806 | } |
807 | |
808 | void Parser::HandlePragmaMSPointersToMembers() { |
809 | assert(Tok.is(tok::annot_pragma_ms_pointers_to_members)); |
810 | LangOptions::PragmaMSPointersToMembersKind RepresentationMethod = |
811 | static_cast<LangOptions::PragmaMSPointersToMembersKind>( |
812 | reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); |
813 | SourceLocation PragmaLoc = ConsumeAnnotationToken(); |
814 | Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc); |
815 | } |
816 | |
817 | void Parser::HandlePragmaMSVtorDisp() { |
818 | assert(Tok.is(tok::annot_pragma_ms_vtordisp)); |
819 | uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()); |
820 | Sema::PragmaMsStackAction Action = |
821 | static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF); |
822 | MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF); |
823 | SourceLocation PragmaLoc = ConsumeAnnotationToken(); |
824 | Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode); |
825 | } |
826 | |
827 | void Parser::HandlePragmaMSPragma() { |
828 | assert(Tok.is(tok::annot_pragma_ms_pragma)); |
829 | |
830 | auto TheTokens = |
831 | (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue(); |
832 | PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true, |
833 | true); |
834 | SourceLocation PragmaLocation = ConsumeAnnotationToken(); |
835 | assert(Tok.isAnyIdentifier()); |
836 | StringRef PragmaName = Tok.getIdentifierInfo()->getName(); |
837 | PP.Lex(Tok); |
838 | |
839 | |
840 | |
841 | typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation); |
842 | PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName) |
843 | .Case("data_seg", &Parser::HandlePragmaMSSegment) |
844 | .Case("bss_seg", &Parser::HandlePragmaMSSegment) |
845 | .Case("const_seg", &Parser::HandlePragmaMSSegment) |
846 | .Case("code_seg", &Parser::HandlePragmaMSSegment) |
847 | .Case("section", &Parser::HandlePragmaMSSection) |
848 | .Case("init_seg", &Parser::HandlePragmaMSInitSeg); |
849 | |
850 | if (!(this->*Handler)(PragmaName, PragmaLocation)) { |
851 | |
852 | |
853 | while (Tok.isNot(tok::eof)) |
854 | PP.Lex(Tok); |
855 | PP.Lex(Tok); |
856 | } |
857 | } |
858 | |
859 | bool Parser::HandlePragmaMSSection(StringRef PragmaName, |
860 | SourceLocation PragmaLocation) { |
861 | if (Tok.isNot(tok::l_paren)) { |
862 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName; |
863 | return false; |
864 | } |
865 | PP.Lex(Tok); |
866 | |
867 | if (Tok.isNot(tok::string_literal)) { |
868 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name) |
869 | << PragmaName; |
870 | return false; |
871 | } |
872 | ExprResult StringResult = ParseStringLiteralExpression(); |
873 | if (StringResult.isInvalid()) |
874 | return false; |
875 | StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get()); |
876 | if (SegmentName->getCharByteWidth() != 1) { |
877 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) |
878 | << PragmaName; |
879 | return false; |
880 | } |
881 | int SectionFlags = ASTContext::PSF_Read; |
882 | bool SectionFlagsAreDefault = true; |
883 | while (Tok.is(tok::comma)) { |
884 | PP.Lex(Tok); |
885 | |
886 | |
887 | |
888 | if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) { |
889 | PP.Lex(Tok); |
890 | continue; |
891 | } |
892 | |
893 | if (!Tok.isAnyIdentifier()) { |
894 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren) |
895 | << PragmaName; |
896 | return false; |
897 | } |
898 | ASTContext::PragmaSectionFlag Flag = |
899 | llvm::StringSwitch<ASTContext::PragmaSectionFlag>( |
900 | Tok.getIdentifierInfo()->getName()) |
901 | .Case("read", ASTContext::PSF_Read) |
902 | .Case("write", ASTContext::PSF_Write) |
903 | .Case("execute", ASTContext::PSF_Execute) |
904 | .Case("shared", ASTContext::PSF_Invalid) |
905 | .Case("nopage", ASTContext::PSF_Invalid) |
906 | .Case("nocache", ASTContext::PSF_Invalid) |
907 | .Case("discard", ASTContext::PSF_Invalid) |
908 | .Case("remove", ASTContext::PSF_Invalid) |
909 | .Default(ASTContext::PSF_None); |
910 | if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) { |
911 | PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None |
912 | ? diag::warn_pragma_invalid_specific_action |
913 | : diag::warn_pragma_unsupported_action) |
914 | << PragmaName << Tok.getIdentifierInfo()->getName(); |
915 | return false; |
916 | } |
917 | SectionFlags |= Flag; |
918 | SectionFlagsAreDefault = false; |
919 | PP.Lex(Tok); |
920 | } |
921 | |
922 | |
923 | if (SectionFlagsAreDefault) |
924 | SectionFlags |= ASTContext::PSF_Write; |
925 | if (Tok.isNot(tok::r_paren)) { |
926 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName; |
927 | return false; |
928 | } |
929 | PP.Lex(Tok); |
930 | if (Tok.isNot(tok::eof)) { |
931 | PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol) |
932 | << PragmaName; |
933 | return false; |
934 | } |
935 | PP.Lex(Tok); |
936 | Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName); |
937 | return true; |
938 | } |
939 | |
940 | bool Parser::HandlePragmaMSSegment(StringRef PragmaName, |
941 | SourceLocation PragmaLocation) { |
942 | if (Tok.isNot(tok::l_paren)) { |
943 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName; |
944 | return false; |
945 | } |
946 | PP.Lex(Tok); |
947 | Sema::PragmaMsStackAction Action = Sema::PSK_Reset; |
948 | StringRef SlotLabel; |
949 | if (Tok.isAnyIdentifier()) { |
950 | StringRef PushPop = Tok.getIdentifierInfo()->getName(); |
951 | if (PushPop == "push") |
952 | Action = Sema::PSK_Push; |
953 | else if (PushPop == "pop") |
954 | Action = Sema::PSK_Pop; |
955 | else { |
956 | PP.Diag(PragmaLocation, |
957 | diag::warn_pragma_expected_section_push_pop_or_name) |
958 | << PragmaName; |
959 | return false; |
960 | } |
961 | if (Action != Sema::PSK_Reset) { |
962 | PP.Lex(Tok); |
963 | if (Tok.is(tok::comma)) { |
964 | PP.Lex(Tok); |
965 | |
966 | if (Tok.isAnyIdentifier()) { |
967 | SlotLabel = Tok.getIdentifierInfo()->getName(); |
968 | PP.Lex(Tok); |
969 | if (Tok.is(tok::comma)) |
970 | PP.Lex(Tok); |
971 | else if (Tok.isNot(tok::r_paren)) { |
972 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) |
973 | << PragmaName; |
974 | return false; |
975 | } |
976 | } |
977 | } else if (Tok.isNot(tok::r_paren)) { |
978 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName; |
979 | return false; |
980 | } |
981 | } |
982 | } |
983 | |
984 | StringLiteral *SegmentName = nullptr; |
985 | if (Tok.isNot(tok::r_paren)) { |
986 | if (Tok.isNot(tok::string_literal)) { |
987 | unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ? |
988 | diag::warn_pragma_expected_section_name : |
989 | diag::warn_pragma_expected_section_label_or_name : |
990 | diag::warn_pragma_expected_section_push_pop_or_name; |
991 | PP.Diag(PragmaLocation, DiagID) << PragmaName; |
992 | return false; |
993 | } |
994 | ExprResult StringResult = ParseStringLiteralExpression(); |
995 | if (StringResult.isInvalid()) |
996 | return false; |
997 | SegmentName = cast<StringLiteral>(StringResult.get()); |
998 | if (SegmentName->getCharByteWidth() != 1) { |
999 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) |
1000 | << PragmaName; |
1001 | return false; |
1002 | } |
1003 | |
1004 | if (SegmentName->getLength()) |
1005 | Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); |
1006 | } |
1007 | if (Tok.isNot(tok::r_paren)) { |
1008 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName; |
1009 | return false; |
1010 | } |
1011 | PP.Lex(Tok); |
1012 | if (Tok.isNot(tok::eof)) { |
1013 | PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol) |
1014 | << PragmaName; |
1015 | return false; |
1016 | } |
1017 | PP.Lex(Tok); |
1018 | Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel, |
1019 | SegmentName, PragmaName); |
1020 | return true; |
1021 | } |
1022 | |
1023 | |
1024 | bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName, |
1025 | SourceLocation PragmaLocation) { |
1026 | if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) { |
1027 | PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target); |
1028 | return false; |
1029 | } |
1030 | |
1031 | if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen, |
1032 | PragmaName)) |
1033 | return false; |
1034 | |
1035 | |
1036 | StringLiteral *SegmentName = nullptr; |
1037 | if (Tok.isAnyIdentifier()) { |
1038 | auto *II = Tok.getIdentifierInfo(); |
1039 | StringRef Section = llvm::StringSwitch<StringRef>(II->getName()) |
1040 | .Case("compiler", "\".CRT$XCC\"") |
1041 | .Case("lib", "\".CRT$XCL\"") |
1042 | .Case("user", "\".CRT$XCU\"") |
1043 | .Default(""); |
1044 | |
1045 | if (!Section.empty()) { |
1046 | |
1047 | Token Toks[1]; |
1048 | Toks[0].startToken(); |
1049 | Toks[0].setKind(tok::string_literal); |
1050 | Toks[0].setLocation(Tok.getLocation()); |
1051 | Toks[0].setLiteralData(Section.data()); |
1052 | Toks[0].setLength(Section.size()); |
1053 | SegmentName = |
1054 | cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get()); |
1055 | PP.Lex(Tok); |
1056 | } |
1057 | } else if (Tok.is(tok::string_literal)) { |
1058 | ExprResult StringResult = ParseStringLiteralExpression(); |
1059 | if (StringResult.isInvalid()) |
1060 | return false; |
1061 | SegmentName = cast<StringLiteral>(StringResult.get()); |
1062 | if (SegmentName->getCharByteWidth() != 1) { |
1063 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) |
1064 | << PragmaName; |
1065 | return false; |
1066 | } |
1067 | |
1068 | } |
1069 | |
1070 | if (!SegmentName) { |
1071 | PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName; |
1072 | return false; |
1073 | } |
1074 | |
1075 | if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen, |
1076 | PragmaName) || |
1077 | ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol, |
1078 | PragmaName)) |
1079 | return false; |
1080 | |
1081 | Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName); |
1082 | return true; |
1083 | } |
1084 | |
1085 | namespace { |
1086 | struct PragmaLoopHintInfo { |
1087 | Token PragmaName; |
1088 | Token Option; |
1089 | ArrayRef<Token> Toks; |
1090 | }; |
1091 | } |
1092 | |
1093 | static std::string PragmaLoopHintString(Token PragmaName, Token Option) { |
1094 | StringRef Str = PragmaName.getIdentifierInfo()->getName(); |
1095 | std::string ClangLoopStr = (llvm::Twine("clang loop ") + Str).str(); |
1096 | return std::string(llvm::StringSwitch<StringRef>(Str) |
1097 | .Case("loop", ClangLoopStr) |
1098 | .Case("unroll_and_jam", Str) |
1099 | .Case("unroll", Str) |
1100 | .Default("")); |
1101 | } |
1102 | |
1103 | bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { |
1104 | assert(Tok.is(tok::annot_pragma_loop_hint)); |
1105 | PragmaLoopHintInfo *Info = |
1106 | static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue()); |
1107 | |
1108 | IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo(); |
1109 | Hint.PragmaNameLoc = IdentifierLoc::create( |
1110 | Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo); |
1111 | |
1112 | |
1113 | |
1114 | IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier) |
1115 | ? Info->Option.getIdentifierInfo() |
1116 | : nullptr; |
1117 | Hint.OptionLoc = IdentifierLoc::create( |
1118 | Actions.Context, Info->Option.getLocation(), OptionInfo); |
1119 | |
1120 | llvm::ArrayRef<Token> Toks = Info->Toks; |
1121 | |
1122 | |
1123 | |
1124 | auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName()) |
1125 | .Cases("unroll", "nounroll", "unroll_and_jam", |
1126 | "nounroll_and_jam", true) |
1127 | .Default(false); |
1128 | |
1129 | if (Toks.empty() && IsLoopHint) { |
1130 | ConsumeAnnotationToken(); |
1131 | Hint.Range = Info->PragmaName.getLocation(); |
1132 | return true; |
1133 | } |
1134 | |
1135 | |
1136 | |
1137 | assert(!Toks.empty() && |
1138 | "PragmaLoopHintInfo::Toks must contain at least one token."); |
1139 | |
1140 | |
1141 | bool OptionUnroll = false; |
1142 | bool OptionUnrollAndJam = false; |
1143 | bool OptionDistribute = false; |
1144 | bool OptionPipelineDisabled = false; |
1145 | bool StateOption = false; |
1146 | if (OptionInfo) { |
1147 | OptionUnroll = OptionInfo->isStr("unroll"); |
1148 | OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam"); |
1149 | OptionDistribute = OptionInfo->isStr("distribute"); |
1150 | OptionPipelineDisabled = OptionInfo->isStr("pipeline"); |
1151 | StateOption = llvm::StringSwitch<bool>(OptionInfo->getName()) |
1152 | .Case("vectorize", true) |
1153 | .Case("interleave", true) |
1154 | .Case("vectorize_predicate", true) |
1155 | .Default(false) || |
1156 | OptionUnroll || OptionUnrollAndJam || OptionDistribute || |
1157 | OptionPipelineDisabled; |
1158 | } |
1159 | |
1160 | bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam && |
1161 | !OptionDistribute && !OptionPipelineDisabled; |
1162 | |
1163 | if (Toks[0].is(tok::eof)) { |
1164 | ConsumeAnnotationToken(); |
1165 | Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument) |
1166 | << StateOption |
1167 | << (OptionUnroll || OptionUnrollAndJam) |
1168 | << AssumeSafetyArg; |
1169 | return false; |
1170 | } |
1171 | |
1172 | |
1173 | if (StateOption) { |
1174 | ConsumeAnnotationToken(); |
1175 | SourceLocation StateLoc = Toks[0].getLocation(); |
1176 | IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo(); |
1177 | |
1178 | bool Valid = StateInfo && |
1179 | llvm::StringSwitch<bool>(StateInfo->getName()) |
1180 | .Case("disable", true) |
1181 | .Case("enable", !OptionPipelineDisabled) |
1182 | .Case("full", OptionUnroll || OptionUnrollAndJam) |
1183 | .Case("assume_safety", AssumeSafetyArg) |
1184 | .Default(false); |
1185 | if (!Valid) { |
1186 | if (OptionPipelineDisabled) { |
1187 | Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword); |
1188 | } else { |
1189 | Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword) |
1190 | << (OptionUnroll || OptionUnrollAndJam) |
1191 | << AssumeSafetyArg; |
1192 | } |
1193 | return false; |
1194 | } |
1195 | if (Toks.size() > 2) |
1196 | Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
1197 | << PragmaLoopHintString(Info->PragmaName, Info->Option); |
1198 | Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo); |
1199 | } else if (OptionInfo && OptionInfo->getName() == "vectorize_width") { |
1200 | PP.EnterTokenStream(Toks, false, |
1201 | false); |
1202 | ConsumeAnnotationToken(); |
1203 | |
1204 | SourceLocation StateLoc = Toks[0].getLocation(); |
1205 | IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo(); |
1206 | StringRef IsScalableStr = StateInfo ? StateInfo->getName() : ""; |
1207 | |
1208 | |
1209 | if (IsScalableStr == "scalable" || IsScalableStr == "fixed") { |
1210 | PP.Lex(Tok); |
1211 | |
1212 | if (Toks.size() > 2) { |
1213 | Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
1214 | << PragmaLoopHintString(Info->PragmaName, Info->Option); |
1215 | while (Tok.isNot(tok::eof)) |
1216 | ConsumeAnyToken(); |
1217 | } |
1218 | |
1219 | Hint.StateLoc = |
1220 | IdentifierLoc::create(Actions.Context, StateLoc, StateInfo); |
1221 | |
1222 | ConsumeToken(); |
1223 | } else { |
1224 | |
1225 | ExprResult R = ParseConstantExpression(); |
1226 | |
1227 | if (R.isInvalid() && !Tok.is(tok::comma)) |
1228 | Diag(Toks[0].getLocation(), |
1229 | diag::note_pragma_loop_invalid_vectorize_option); |
1230 | |
1231 | bool Arg2Error = false; |
1232 | if (Tok.is(tok::comma)) { |
1233 | PP.Lex(Tok); |
1234 | |
1235 | StateInfo = Tok.getIdentifierInfo(); |
1236 | IsScalableStr = StateInfo->getName(); |
1237 | |
1238 | if (IsScalableStr != "scalable" && IsScalableStr != "fixed") { |
1239 | Diag(Tok.getLocation(), |
1240 | diag::err_pragma_loop_invalid_vectorize_option); |
1241 | Arg2Error = true; |
1242 | } else |
1243 | Hint.StateLoc = |
1244 | IdentifierLoc::create(Actions.Context, StateLoc, StateInfo); |
1245 | |
1246 | PP.Lex(Tok); |
1247 | } |
1248 | |
1249 | |
1250 | |
1251 | if (Tok.isNot(tok::eof)) { |
1252 | Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
1253 | << PragmaLoopHintString(Info->PragmaName, Info->Option); |
1254 | while (Tok.isNot(tok::eof)) |
1255 | ConsumeAnyToken(); |
1256 | } |
1257 | |
1258 | ConsumeToken(); |
1259 | |
1260 | if (Arg2Error || R.isInvalid() || |
1261 | Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation())) |
1262 | return false; |
1263 | |
1264 | |
1265 | Hint.ValueExpr = R.get(); |
1266 | } |
1267 | } else { |
1268 | |
1269 | PP.EnterTokenStream(Toks, false, |
1270 | false); |
1271 | ConsumeAnnotationToken(); |
1272 | ExprResult R = ParseConstantExpression(); |
1273 | |
1274 | |
1275 | |
1276 | if (Tok.isNot(tok::eof)) { |
1277 | Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
1278 | << PragmaLoopHintString(Info->PragmaName, Info->Option); |
1279 | while (Tok.isNot(tok::eof)) |
1280 | ConsumeAnyToken(); |
1281 | } |
1282 | |
1283 | ConsumeToken(); |
1284 | |
1285 | if (R.isInvalid() || |
1286 | Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation())) |
1287 | return false; |
1288 | |
1289 | |
1290 | Hint.ValueExpr = R.get(); |
1291 | } |
1292 | |
1293 | Hint.Range = SourceRange(Info->PragmaName.getLocation(), |
1294 | Info->Toks.back().getLocation()); |
1295 | return true; |
1296 | } |
1297 | |
1298 | namespace { |
1299 | struct PragmaAttributeInfo { |
1300 | enum ActionType { Push, Pop, Attribute }; |
1301 | ParsedAttributes &Attributes; |
1302 | ActionType Action; |
1303 | const IdentifierInfo *Namespace = nullptr; |
1304 | ArrayRef<Token> Tokens; |
1305 | |
1306 | PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {} |
1307 | }; |
1308 | |
1309 | #include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc" |
1310 | |
1311 | } |
1312 | |
1313 | static StringRef getIdentifier(const Token &Tok) { |
1314 | if (Tok.is(tok::identifier)) |
1315 | return Tok.getIdentifierInfo()->getName(); |
1316 | const char *S = tok::getKeywordSpelling(Tok.getKind()); |
1317 | if (!S) |
1318 | return ""; |
1319 | return S; |
1320 | } |
1321 | |
1322 | static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) { |
1323 | using namespace attr; |
1324 | switch (Rule) { |
1325 | #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \ |
1326 | case Value: \ |
1327 | return IsAbstract; |
1328 | #include "clang/Basic/AttrSubMatchRulesList.inc" |
1329 | } |
1330 | llvm_unreachable("Invalid attribute subject match rule"); |
1331 | return false; |
1332 | } |
1333 | |
1334 | static void diagnoseExpectedAttributeSubjectSubRule( |
1335 | Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName, |
1336 | SourceLocation SubRuleLoc) { |
1337 | auto Diagnostic = |
1338 | PRef.Diag(SubRuleLoc, |
1339 | diag::err_pragma_attribute_expected_subject_sub_identifier) |
1340 | << PrimaryRuleName; |
1341 | if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule)) |
1342 | Diagnostic << 1 << SubRules; |
1343 | else |
1344 | Diagnostic << 0; |
1345 | } |
1346 | |
1347 | static void diagnoseUnknownAttributeSubjectSubRule( |
1348 | Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName, |
1349 | StringRef SubRuleName, SourceLocation SubRuleLoc) { |
1350 | |
1351 | auto Diagnostic = |
1352 | PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule) |
1353 | << SubRuleName << PrimaryRuleName; |
1354 | if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule)) |
1355 | Diagnostic << 1 << SubRules; |
1356 | else |
1357 | Diagnostic << 0; |
1358 | } |
1359 | |
1360 | bool Parser::ParsePragmaAttributeSubjectMatchRuleSet( |
1361 | attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc, |
1362 | SourceLocation &LastMatchRuleEndLoc) { |
1363 | bool IsAny = false; |
1364 | BalancedDelimiterTracker AnyParens(*this, tok::l_paren); |
1365 | if (getIdentifier(Tok) == "any") { |
1366 | AnyLoc = ConsumeToken(); |
1367 | IsAny = true; |
1368 | if (AnyParens.expectAndConsume()) |
1369 | return true; |
1370 | } |
1371 | |
1372 | do { |
1373 | |
1374 | StringRef Name = getIdentifier(Tok); |
1375 | if (Name.empty()) { |
1376 | Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier); |
1377 | return true; |
1378 | } |
1379 | std::pair<Optional<attr::SubjectMatchRule>, |
1380 | Optional<attr::SubjectMatchRule> (*)(StringRef, bool)> |
1381 | Rule = isAttributeSubjectMatchRule(Name); |
1382 | if (!Rule.first) { |
1383 | Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name; |
1384 | return true; |
1385 | } |
1386 | attr::SubjectMatchRule PrimaryRule = *Rule.first; |
1387 | SourceLocation RuleLoc = ConsumeToken(); |
1388 | |
1389 | BalancedDelimiterTracker Parens(*this, tok::l_paren); |
1390 | if (isAbstractAttrMatcherRule(PrimaryRule)) { |
1391 | if (Parens.expectAndConsume()) |
1392 | return true; |
1393 | } else if (Parens.consumeOpen()) { |
1394 | if (!SubjectMatchRules |
1395 | .insert( |
1396 | std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc))) |
1397 | .second) |
1398 | Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject) |
1399 | << Name |
1400 | << FixItHint::CreateRemoval(SourceRange( |
1401 | RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc)); |
1402 | LastMatchRuleEndLoc = RuleLoc; |
1403 | continue; |
1404 | } |
1405 | |
1406 | |
1407 | StringRef SubRuleName = getIdentifier(Tok); |
1408 | if (SubRuleName.empty()) { |
1409 | diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name, |
1410 | Tok.getLocation()); |
1411 | return true; |
1412 | } |
1413 | attr::SubjectMatchRule SubRule; |
1414 | if (SubRuleName == "unless") { |
1415 | SourceLocation SubRuleLoc = ConsumeToken(); |
1416 | BalancedDelimiterTracker Parens(*this, tok::l_paren); |
1417 | if (Parens.expectAndConsume()) |
1418 | return true; |
1419 | SubRuleName = getIdentifier(Tok); |
1420 | if (SubRuleName.empty()) { |
1421 | diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name, |
1422 | SubRuleLoc); |
1423 | return true; |
1424 | } |
1425 | auto SubRuleOrNone = Rule.second(SubRuleName, true); |
1426 | if (!SubRuleOrNone) { |
1427 | std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")"; |
1428 | diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name, |
1429 | SubRuleUnlessName, SubRuleLoc); |
1430 | return true; |
1431 | } |
1432 | SubRule = *SubRuleOrNone; |
1433 | ConsumeToken(); |
1434 | if (Parens.consumeClose()) |
1435 | return true; |
1436 | } else { |
1437 | auto SubRuleOrNone = Rule.second(SubRuleName, false); |
1438 | if (!SubRuleOrNone) { |
1439 | diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name, |
1440 | SubRuleName, Tok.getLocation()); |
1441 | return true; |
1442 | } |
1443 | SubRule = *SubRuleOrNone; |
1444 | ConsumeToken(); |
1445 | } |
1446 | SourceLocation RuleEndLoc = Tok.getLocation(); |
1447 | LastMatchRuleEndLoc = RuleEndLoc; |
1448 | if (Parens.consumeClose()) |
1449 | return true; |
1450 | if (!SubjectMatchRules |
1451 | .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc))) |
1452 | .second) { |
1453 | Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject) |
1454 | << attr::getSubjectMatchRuleSpelling(SubRule) |
1455 | << FixItHint::CreateRemoval(SourceRange( |
1456 | RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc)); |
1457 | continue; |
1458 | } |
1459 | } while (IsAny && TryConsumeToken(tok::comma)); |
1460 | |
1461 | if (IsAny) |
1462 | if (AnyParens.consumeClose()) |
1463 | return true; |
1464 | |
1465 | return false; |
1466 | } |
1467 | |
1468 | namespace { |
1469 | |
1470 | |
1471 | enum class MissingAttributeSubjectRulesRecoveryPoint { |
1472 | Comma, |
1473 | ApplyTo, |
1474 | Equals, |
1475 | Any, |
1476 | None, |
1477 | }; |
1478 | |
1479 | MissingAttributeSubjectRulesRecoveryPoint |
1480 | getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) { |
1481 | if (const auto *II = Tok.getIdentifierInfo()) { |
1482 | if (II->isStr("apply_to")) |
1483 | return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo; |
1484 | if (II->isStr("any")) |
1485 | return MissingAttributeSubjectRulesRecoveryPoint::Any; |
1486 | } |
1487 | if (Tok.is(tok::equal)) |
1488 | return MissingAttributeSubjectRulesRecoveryPoint::Equals; |
1489 | return MissingAttributeSubjectRulesRecoveryPoint::None; |
1490 | } |
1491 | |
1492 | |
1493 | |
1494 | |
1495 | DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic( |
1496 | unsigned DiagID, ParsedAttr &Attribute, |
1497 | MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) { |
1498 | SourceLocation Loc = PRef.getEndOfPreviousToken(); |
1499 | if (Loc.isInvalid()) |
| |
1500 | Loc = PRef.getCurToken().getLocation(); |
1501 | auto Diagnostic = PRef.Diag(Loc, DiagID); |
1502 | std::string FixIt; |
1503 | MissingAttributeSubjectRulesRecoveryPoint EndPoint = |
1504 | getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken()); |
1505 | if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma) |
| |
1506 | FixIt = ", "; |
1507 | if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo && |
| |
1508 | EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo) |
1509 | FixIt += "apply_to"; |
1510 | if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals && |
| |
1511 | EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals) |
1512 | FixIt += " = "; |
1513 | SourceRange FixItRange(Loc); |
1514 | if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) { |
| |
1515 | |
1516 | SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet; |
1517 | Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet); |
1518 | if (SubjectMatchRuleSet.empty()) { |
| |
1519 | |
1520 | |
1521 | return Diagnostic; |
| 21 | | Calling copy constructor for 'DiagnosticBuilder' | |
|
| 27 | | Returning from copy constructor for 'DiagnosticBuilder' | |
|
| 28 | | Calling '~DiagnosticBuilder' | |
|
| 36 | | Returning from '~DiagnosticBuilder' | |
|
1522 | } |
1523 | FixIt += "any("; |
1524 | bool NeedsComma = false; |
1525 | for (const auto &I : SubjectMatchRuleSet) { |
1526 | |
1527 | |
1528 | if (!I.second) |
1529 | continue; |
1530 | if (NeedsComma) |
1531 | FixIt += ", "; |
1532 | else |
1533 | NeedsComma = true; |
1534 | FixIt += attr::getSubjectMatchRuleSpelling(I.first); |
1535 | } |
1536 | FixIt += ")"; |
1537 | |
1538 | PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch); |
1539 | FixItRange.setEnd(PRef.getCurToken().getLocation()); |
1540 | } |
1541 | if (FixItRange.getBegin() == FixItRange.getEnd()) |
1542 | Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt); |
1543 | else |
1544 | Diagnostic << FixItHint::CreateReplacement( |
1545 | CharSourceRange::getCharRange(FixItRange), FixIt); |
1546 | return Diagnostic; |
1547 | } |
1548 | |
1549 | } |
1550 | |
1551 | void Parser::HandlePragmaAttribute() { |
1552 | assert(Tok.is(tok::annot_pragma_attribute) && |
1553 | "Expected #pragma attribute annotation token"); |
1554 | SourceLocation PragmaLoc = Tok.getLocation(); |
1555 | auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue()); |
1556 | if (Info->Action == PragmaAttributeInfo::Pop) { |
| 1 | Assuming field 'Action' is not equal to Pop | |
|
| |
1557 | ConsumeAnnotationToken(); |
1558 | Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace); |
1559 | return; |
1560 | } |
1561 | |
1562 | assert((Info->Action == PragmaAttributeInfo::Push || |
1563 | Info->Action == PragmaAttributeInfo::Attribute) && |
1564 | "Unexpected #pragma attribute command"); |
1565 | |
1566 | if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) { |
| 3 | | Assuming field 'Action' is not equal to Push | |
|
1567 | ConsumeAnnotationToken(); |
1568 | Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace); |
1569 | return; |
1570 | } |
1571 | |
1572 | PP.EnterTokenStream(Info->Tokens, false, |
1573 | false); |
1574 | ConsumeAnnotationToken(); |
1575 | |
1576 | ParsedAttributes &Attrs = Info->Attributes; |
1577 | Attrs.clearListOnly(); |
1578 | |
1579 | auto SkipToEnd = [this]() { |
1580 | SkipUntil(tok::eof, StopBeforeMatch); |
1581 | ConsumeToken(); |
1582 | }; |
1583 | |
1584 | if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) { |
1585 | |
1586 | ParseCXX11AttributeSpecifier(Attrs); |
1587 | } else if (Tok.is(tok::kw___attribute)) { |
| |
1588 | ConsumeToken(); |
1589 | if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, |
1590 | "attribute")) |
1591 | return SkipToEnd(); |
1592 | if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) |
1593 | return SkipToEnd(); |
1594 | |
1595 | if (Tok.isNot(tok::identifier)) { |
1596 | Diag(Tok, diag::err_pragma_attribute_expected_attribute_name); |
1597 | SkipToEnd(); |
1598 | return; |
1599 | } |
1600 | IdentifierInfo *AttrName = Tok.getIdentifierInfo(); |
1601 | SourceLocation AttrNameLoc = ConsumeToken(); |
1602 | |
1603 | if (Tok.isNot(tok::l_paren)) |
1604 | Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, |
1605 | ParsedAttr::AS_GNU); |
1606 | else |
1607 | ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, nullptr, |
1608 | nullptr, |
1609 | SourceLocation(), ParsedAttr::AS_GNU, |
1610 | nullptr); |
1611 | |
1612 | if (ExpectAndConsume(tok::r_paren)) |
1613 | return SkipToEnd(); |
1614 | if (ExpectAndConsume(tok::r_paren)) |
1615 | return SkipToEnd(); |
1616 | } else if (Tok.is(tok::kw___declspec)) { |
| |
1617 | ParseMicrosoftDeclSpecs(Attrs); |
1618 | } else { |
1619 | Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax); |
1620 | if (Tok.getIdentifierInfo()) { |
1621 | |
1622 | |
1623 | if (ParsedAttr::getParsedKind( |
1624 | Tok.getIdentifierInfo(), nullptr, |
1625 | ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) { |
1626 | SourceLocation InsertStartLoc = Tok.getLocation(); |
1627 | ConsumeToken(); |
1628 | if (Tok.is(tok::l_paren)) { |
1629 | ConsumeAnyToken(); |
1630 | SkipUntil(tok::r_paren, StopBeforeMatch); |
1631 | if (Tok.isNot(tok::r_paren)) |
1632 | return SkipToEnd(); |
1633 | } |
1634 | Diag(Tok, diag::note_pragma_attribute_use_attribute_kw) |
1635 | << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((") |
1636 | << FixItHint::CreateInsertion(Tok.getEndLoc(), "))"); |
1637 | } |
1638 | } |
1639 | SkipToEnd(); |
1640 | return; |
1641 | } |
1642 | |
1643 | if (Attrs.empty() || Attrs.begin()->isInvalid()) { |
| 6 | | Assuming the condition is false | |
|
| 7 | | Assuming the condition is false | |
|
| |
1644 | SkipToEnd(); |
1645 | return; |
1646 | } |
1647 | |
1648 | |
1649 | if (Attrs.size() > 1) { |
| 9 | | Assuming the condition is false | |
|
| |
1650 | SourceLocation Loc = Attrs[1].getLoc(); |
1651 | Diag(Loc, diag::err_pragma_attribute_multiple_attributes); |
1652 | SkipToEnd(); |
1653 | return; |
1654 | } |
1655 | |
1656 | ParsedAttr &Attribute = *Attrs.begin(); |
1657 | if (!Attribute.isSupportedByPragmaAttribute()) { |
| 11 | | Assuming the condition is false | |
|
| |
1658 | Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute) |
1659 | << Attribute; |
1660 | SkipToEnd(); |
1661 | return; |
1662 | } |
1663 | |
1664 | |
1665 | if (!TryConsumeToken(tok::comma)) { |
| |
1666 | createExpectedAttributeSubjectRulesTokenDiagnostic( |
| 14 | | Calling 'createExpectedAttributeSubjectRulesTokenDiagnostic' | |
|
| 37 | | Returning from 'createExpectedAttributeSubjectRulesTokenDiagnostic' | |
|
| 38 | | Calling 'DiagnosticBuilder::operator<<' | |
|
1667 | diag::err_expected, Attribute, |
1668 | MissingAttributeSubjectRulesRecoveryPoint::Comma, *this) |
1669 | << tok::comma; |
1670 | SkipToEnd(); |
1671 | return; |
1672 | } |
1673 | |
1674 | if (Tok.isNot(tok::identifier)) { |
1675 | createExpectedAttributeSubjectRulesTokenDiagnostic( |
1676 | diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute, |
1677 | MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this); |
1678 | SkipToEnd(); |
1679 | return; |
1680 | } |
1681 | const IdentifierInfo *II = Tok.getIdentifierInfo(); |
1682 | if (!II->isStr("apply_to")) { |
1683 | createExpectedAttributeSubjectRulesTokenDiagnostic( |
1684 | diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute, |
1685 | MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this); |
1686 | SkipToEnd(); |
1687 | return; |
1688 | } |
1689 | ConsumeToken(); |
1690 | |
1691 | if (!TryConsumeToken(tok::equal)) { |
1692 | createExpectedAttributeSubjectRulesTokenDiagnostic( |
1693 | diag::err_expected, Attribute, |
1694 | MissingAttributeSubjectRulesRecoveryPoint::Equals, *this) |
1695 | << tok::equal; |
1696 | SkipToEnd(); |
1697 | return; |
1698 | } |
1699 | |
1700 | attr::ParsedSubjectMatchRuleSet SubjectMatchRules; |
1701 | SourceLocation AnyLoc, LastMatchRuleEndLoc; |
1702 | if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc, |
1703 | LastMatchRuleEndLoc)) { |
1704 | SkipToEnd(); |
1705 | return; |
1706 | } |
1707 | |
1708 | |
1709 | |
1710 | if (Tok.isNot(tok::eof)) { |
1711 | Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute); |
1712 | SkipToEnd(); |
1713 | return; |
1714 | } |
1715 | |
1716 | |
1717 | ConsumeToken(); |
1718 | |
1719 | |
1720 | if (Info->Action == PragmaAttributeInfo::Push) |
1721 | Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace); |
1722 | |
1723 | Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc, |
1724 | std::move(SubjectMatchRules)); |
1725 | } |
1726 | |
1727 | |
1728 | |
1729 | |
1730 | void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, |
1731 | PragmaIntroducer Introducer, |
1732 | Token &VisTok) { |
1733 | SourceLocation VisLoc = VisTok.getLocation(); |
1734 | |
1735 | Token Tok; |
1736 | PP.LexUnexpandedToken(Tok); |
1737 | |
1738 | const IdentifierInfo *PushPop = Tok.getIdentifierInfo(); |
1739 | |
1740 | const IdentifierInfo *VisType; |
1741 | if (PushPop && PushPop->isStr("pop")) { |
1742 | VisType = nullptr; |
1743 | } else if (PushPop && PushPop->isStr("push")) { |
1744 | PP.LexUnexpandedToken(Tok); |
1745 | if (Tok.isNot(tok::l_paren)) { |
1746 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) |
1747 | << "visibility"; |
1748 | return; |
1749 | } |
1750 | PP.LexUnexpandedToken(Tok); |
1751 | VisType = Tok.getIdentifierInfo(); |
1752 | if (!VisType) { |
1753 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) |
1754 | << "visibility"; |
1755 | return; |
1756 | } |
1757 | PP.LexUnexpandedToken(Tok); |
1758 | if (Tok.isNot(tok::r_paren)) { |
1759 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) |
1760 | << "visibility"; |
1761 | return; |
1762 | } |
1763 | } else { |
1764 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) |
1765 | << "visibility"; |
1766 | return; |
1767 | } |
1768 | SourceLocation EndLoc = Tok.getLocation(); |
1769 | PP.LexUnexpandedToken(Tok); |
1770 | if (Tok.isNot(tok::eod)) { |
1771 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
1772 | << "visibility"; |
1773 | return; |
1774 | } |
1775 | |
1776 | auto Toks = std::make_unique<Token[]>(1); |
1777 | Toks[0].startToken(); |
1778 | Toks[0].setKind(tok::annot_pragma_vis); |
1779 | Toks[0].setLocation(VisLoc); |
1780 | Toks[0].setAnnotationEndLoc(EndLoc); |
1781 | Toks[0].setAnnotationValue( |
1782 | const_cast<void *>(static_cast<const void *>(VisType))); |
1783 | PP.EnterTokenStream(std::move(Toks), 1, true, |
1784 | false); |
1785 | } |
1786 | |
1787 | |
1788 | |
1789 | |
1790 | |
1791 | void PragmaPackHandler::HandlePragma(Preprocessor &PP, |
1792 | PragmaIntroducer Introducer, |
1793 | Token &PackTok) { |
1794 | SourceLocation PackLoc = PackTok.getLocation(); |
1795 | |
1796 | Token Tok; |
1797 | PP.Lex(Tok); |
1798 | if (Tok.isNot(tok::l_paren)) { |
1799 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack"; |
1800 | return; |
1801 | } |
1802 | |
1803 | Sema::PragmaMsStackAction Action = Sema::PSK_Reset; |
1804 | StringRef SlotLabel; |
1805 | Token Alignment; |
1806 | Alignment.startToken(); |
1807 | PP.Lex(Tok); |
1808 | if (Tok.is(tok::numeric_constant)) { |
1809 | Alignment = Tok; |
1810 | |
1811 | PP.Lex(Tok); |
1812 | |
1813 | |
1814 | |
1815 | |
1816 | Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack) |
1817 | ? Sema::PSK_Push_Set |
1818 | : Sema::PSK_Set; |
1819 | } else if (Tok.is(tok::identifier)) { |
1820 | const IdentifierInfo *II = Tok.getIdentifierInfo(); |
1821 | if (II->isStr("show")) { |
1822 | Action = Sema::PSK_Show; |
1823 | PP.Lex(Tok); |
1824 | } else { |
1825 | if (II->isStr("push")) { |
1826 | Action = Sema::PSK_Push; |
1827 | } else if (II->isStr("pop")) { |
1828 | Action = Sema::PSK_Pop; |
1829 | } else { |
1830 | PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack"; |
1831 | return; |
1832 | } |
1833 | PP.Lex(Tok); |
1834 | |
1835 | if (Tok.is(tok::comma)) { |
1836 | PP.Lex(Tok); |
1837 | |
1838 | if (Tok.is(tok::numeric_constant)) { |
1839 | Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); |
1840 | Alignment = Tok; |
1841 | |
1842 | PP.Lex(Tok); |
1843 | } else if (Tok.is(tok::identifier)) { |
1844 | SlotLabel = Tok.getIdentifierInfo()->getName(); |
1845 | PP.Lex(Tok); |
1846 | |
1847 | if (Tok.is(tok::comma)) { |
1848 | PP.Lex(Tok); |
1849 | |
1850 | if (Tok.isNot(tok::numeric_constant)) { |
1851 | PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); |
1852 | return; |
1853 | } |
1854 | |
1855 | Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); |
1856 | Alignment = Tok; |
1857 | |
1858 | PP.Lex(Tok); |
1859 | } |
1860 | } else { |
1861 | PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); |
1862 | return; |
1863 | } |
1864 | } |
1865 | } |
1866 | } else if (PP.getLangOpts().ApplePragmaPack || |
1867 | PP.getLangOpts().XLPragmaPack) { |
1868 | |
1869 | |
1870 | |
1871 | |
1872 | Action = Sema::PSK_Pop; |
1873 | } |
1874 | |
1875 | if (Tok.isNot(tok::r_paren)) { |
1876 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack"; |
1877 | return; |
1878 | } |
1879 | |
1880 | SourceLocation RParenLoc = Tok.getLocation(); |
1881 | PP.Lex(Tok); |
1882 | if (Tok.isNot(tok::eod)) { |
1883 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack"; |
1884 | return; |
1885 | } |
1886 | |
1887 | PragmaPackInfo *Info = |
1888 | PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1); |
1889 | Info->Action = Action; |
1890 | Info->SlotLabel = SlotLabel; |
1891 | Info->Alignment = Alignment; |
1892 | |
1893 | MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), |
1894 | 1); |
1895 | Toks[0].startToken(); |
1896 | Toks[0].setKind(tok::annot_pragma_pack); |
1897 | Toks[0].setLocation(PackLoc); |
1898 | Toks[0].setAnnotationEndLoc(RParenLoc); |
1899 | Toks[0].setAnnotationValue(static_cast<void*>(Info)); |
1900 | PP.EnterTokenStream(Toks, true, |
1901 | false); |
1902 | } |
1903 | |
1904 | |
1905 | |
1906 | void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, |
1907 | PragmaIntroducer Introducer, |
1908 | Token &MSStructTok) { |
1909 | PragmaMSStructKind Kind = PMSST_OFF; |
1910 | |
1911 | Token Tok; |
1912 | PP.Lex(Tok); |
1913 | if (Tok.isNot(tok::identifier)) { |
1914 | PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); |
1915 | return; |
1916 | } |
1917 | SourceLocation EndLoc = Tok.getLocation(); |
1918 | const IdentifierInfo *II = Tok.getIdentifierInfo(); |
1919 | if (II->isStr("on")) { |
1920 | Kind = PMSST_ON; |
1921 | PP.Lex(Tok); |
1922 | } |
1923 | else if (II->isStr("off") || II->isStr("reset")) |
1924 | PP.Lex(Tok); |
1925 | else { |
1926 | PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); |
1927 | return; |
1928 | } |
1929 | |
1930 | if (Tok.isNot(tok::eod)) { |
1931 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
1932 | << "ms_struct"; |
1933 | return; |
1934 | } |
1935 | |
1936 | MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), |
1937 | 1); |
1938 | Toks[0].startToken(); |
1939 | Toks[0].setKind(tok::annot_pragma_msstruct); |
1940 | Toks[0].setLocation(MSStructTok.getLocation()); |
1941 | Toks[0].setAnnotationEndLoc(EndLoc); |
1942 | Toks[0].setAnnotationValue(reinterpret_cast<void*>( |
1943 | static_cast<uintptr_t>(Kind))); |
1944 | PP.EnterTokenStream(Toks, true, |
1945 | false); |
1946 | } |
1947 | |
1948 | |
1949 | void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP, |
1950 | PragmaIntroducer Introducer, |
1951 | Token &FirstToken) { |
1952 | |
1953 | Token Tok; |
1954 | auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid; |
1955 | |
1956 | PP.Lex(Tok); |
1957 | while (Tok.isNot(tok::eod)) { |
1958 | if (Tok.isNot(tok::identifier)) { |
1959 | PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section"; |
1960 | return; |
1961 | } |
1962 | |
1963 | const IdentifierInfo *SecType = Tok.getIdentifierInfo(); |
1964 | if (SecType->isStr("bss")) |
1965 | SecKind = Sema::PragmaClangSectionKind::PCSK_BSS; |
1966 | else if (SecType->isStr("data")) |
1967 | SecKind = Sema::PragmaClangSectionKind::PCSK_Data; |
1968 | else if (SecType->isStr("rodata")) |
1969 | SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata; |
1970 | else if (SecType->isStr("relro")) |
1971 | SecKind = Sema::PragmaClangSectionKind::PCSK_Relro; |
1972 | else if (SecType->isStr("text")) |
1973 | SecKind = Sema::PragmaClangSectionKind::PCSK_Text; |
1974 | else { |
1975 | PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section"; |
1976 | return; |
1977 | } |
1978 | |
1979 | SourceLocation PragmaLocation = Tok.getLocation(); |
1980 | PP.Lex(Tok); |
1981 | if (Tok.isNot(tok::equal)) { |
1982 | PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind; |
1983 | return; |
1984 | } |
1985 | |
1986 | std::string SecName; |
1987 | if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false)) |
1988 | return; |
1989 | |
1990 | Actions.ActOnPragmaClangSection( |
1991 | PragmaLocation, |
1992 | (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set |
1993 | : Sema::PragmaClangSectionAction::PCSA_Clear), |
1994 | SecKind, SecName); |
1995 | } |
1996 | } |
1997 | |
1998 | |
1999 | |
2000 | |
2001 | static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, |
2002 | bool IsOptions) { |
2003 | Token Tok; |
2004 | |
2005 | if (IsOptions) { |
2006 | PP.Lex(Tok); |
2007 | if (Tok.isNot(tok::identifier) || |
2008 | !Tok.getIdentifierInfo()->isStr("align")) { |
2009 | PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align); |
2010 | return; |
2011 | } |
2012 | } |
2013 | |
2014 | PP.Lex(Tok); |
2015 | if (PP.getLangOpts().XLPragmaPack) { |
2016 | if (Tok.isNot(tok::l_paren)) { |
2017 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align"; |
2018 | return; |
2019 | } |
2020 | } else if (Tok.isNot(tok::equal)) { |
2021 | PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal) |
2022 | << IsOptions; |
2023 | return; |
2024 | } |
2025 | |
2026 | PP.Lex(Tok); |
2027 | if (Tok.isNot(tok::identifier)) { |
2028 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) |
2029 | << (IsOptions ? "options" : "align"); |
2030 | return; |
2031 | } |
2032 | |
2033 | Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural; |
2034 | const IdentifierInfo *II = Tok.getIdentifierInfo(); |
2035 | if (II->isStr("native")) |
2036 | Kind = Sema::POAK_Native; |
2037 | else if (II->isStr("natural")) |
2038 | Kind = Sema::POAK_Natural; |
2039 | else if (II->isStr("packed")) |
2040 | Kind = Sema::POAK_Packed; |
2041 | else if (II->isStr("power")) |
2042 | Kind = Sema::POAK_Power; |
2043 | else if (II->isStr("mac68k")) |
2044 | Kind = Sema::POAK_Mac68k; |
2045 | else if (II->isStr("reset")) |
2046 | Kind = Sema::POAK_Reset; |
2047 | else { |
2048 | PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option) |
2049 | << IsOptions; |
2050 | return; |
2051 | } |
2052 | |
2053 | if (PP.getLangOpts().XLPragmaPack) { |
2054 | PP.Lex(Tok); |
2055 | if (Tok.isNot(tok::r_paren)) { |
2056 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align"; |
2057 | return; |
2058 | } |
2059 | } |
2060 | |
2061 | SourceLocation EndLoc = Tok.getLocation(); |
2062 | PP.Lex(Tok); |
2063 | if (Tok.isNot(tok::eod)) { |
2064 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
2065 | << (IsOptions ? "options" : "align"); |
2066 | return; |
2067 | } |
2068 | |
2069 | MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), |
2070 | 1); |
2071 | Toks[0].startToken(); |
2072 | Toks[0].setKind(tok::annot_pragma_align); |
2073 | Toks[0].setLocation(FirstTok.getLocation()); |
2074 | Toks[0].setAnnotationEndLoc(EndLoc); |
2075 | Toks[0].setAnnotationValue(reinterpret_cast<void*>( |
2076 | static_cast<uintptr_t>(Kind))); |
2077 | PP.EnterTokenStream(Toks, true, |
2078 | false); |
2079 | } |
2080 | |
2081 | void PragmaAlignHandler::HandlePragma(Preprocessor &PP, |
2082 | PragmaIntroducer Introducer, |
2083 | Token &AlignTok) { |
2084 | ParseAlignPragma(PP, AlignTok, false); |
2085 | } |
2086 | |
2087 | void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, |
2088 | PragmaIntroducer Introducer, |
2089 | Token &OptionsTok) { |
2090 | ParseAlignPragma(PP, OptionsTok, true); |
2091 | } |
2092 | |
2093 | |
2094 | void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, |
2095 | PragmaIntroducer Introducer, |
2096 | Token &UnusedTok) { |
2097 | |
2098 | SourceLocation UnusedLoc = UnusedTok.getLocation(); |
2099 | |
2100 | |
2101 | Token Tok; |
2102 | PP.Lex(Tok); |
2103 | if (Tok.isNot(tok::l_paren)) { |
2104 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; |
2105 | return; |
2106 | } |
2107 | |
2108 | |
2109 | SmallVector<Token, 5> Identifiers; |
2110 | SourceLocation RParenLoc; |
2111 | bool LexID = true; |
2112 | |
2113 | while (true) { |
2114 | PP.Lex(Tok); |
2115 | |
2116 | if (LexID) { |
2117 | if (Tok.is(tok::identifier)) { |
2118 | Identifiers.push_back(Tok); |
2119 | LexID = false; |
2120 | continue; |
2121 | } |
2122 | |
2123 | |
2124 | PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); |
2125 | return; |
2126 | } |
2127 | |
2128 | |
2129 | if (Tok.is(tok::comma)) { |
2130 | LexID = true; |
2131 | continue; |
2132 | } |
2133 | |
2134 | if (Tok.is(tok::r_paren)) { |
2135 | RParenLoc = Tok.getLocation(); |
2136 | break; |
2137 | } |
2138 | |
2139 | |
2140 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused"; |
2141 | return; |
2142 | } |
2143 | |
2144 | PP.Lex(Tok); |
2145 | if (Tok.isNot(tok::eod)) { |
2146 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << |
2147 | "unused"; |
2148 | return; |
2149 | } |
2150 | |
2151 | |
2152 | assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); |
2153 | assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments"); |
2154 | |
2155 | |
2156 | |
2157 | |
2158 | |
2159 | |
2160 | MutableArrayRef<Token> Toks( |
2161 | PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()), |
2162 | 2 * Identifiers.size()); |
2163 | for (unsigned i=0; i != Identifiers.size(); i++) { |
2164 | Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1]; |
2165 | pragmaUnusedTok.startToken(); |
2166 | pragmaUnusedTok.setKind(tok::annot_pragma_unused); |
2167 | pragmaUnusedTok.setLocation(UnusedLoc); |
2168 | idTok = Identifiers[i]; |
2169 | } |
2170 | PP.EnterTokenStream(Toks, true, |
2171 | false); |
2172 | } |
2173 | |
2174 | |
2175 | |
2176 | void PragmaWeakHandler::HandlePragma(Preprocessor &PP, |
2177 | PragmaIntroducer Introducer, |
2178 | Token &WeakTok) { |
2179 | SourceLocation WeakLoc = WeakTok.getLocation(); |
2180 | |
2181 | Token Tok; |
2182 | PP.Lex(Tok); |
2183 | if (Tok.isNot(tok::identifier)) { |
2184 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak"; |
2185 | return; |
2186 | } |
2187 | |
2188 | Token WeakName = Tok; |
2189 | bool HasAlias = false; |
2190 | Token AliasName; |
2191 | |
2192 | PP.Lex(Tok); |
2193 | if (Tok.is(tok::equal)) { |
2194 | HasAlias = true; |
2195 | PP.Lex(Tok); |
2196 | if (Tok.isNot(tok::identifier)) { |
2197 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) |
2198 | << "weak"; |
2199 | return; |
2200 | } |
2201 | AliasName = Tok; |
2202 | PP.Lex(Tok); |
2203 | } |
2204 | |
2205 | if (Tok.isNot(tok::eod)) { |
2206 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak"; |
2207 | return; |
2208 | } |
2209 | |
2210 | if (HasAlias) { |
2211 | MutableArrayRef<Token> Toks( |
2212 | PP.getPreprocessorAllocator().Allocate<Token>(3), 3); |
2213 | Token &pragmaUnusedTok = Toks[0]; |
2214 | pragmaUnusedTok.startToken(); |
2215 | pragmaUnusedTok.setKind(tok::annot_pragma_weakalias); |
2216 | pragmaUnusedTok.setLocation(WeakLoc); |
2217 | pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation()); |
2218 | Toks[1] = WeakName; |
2219 | Toks[2] = AliasName; |
2220 | PP.EnterTokenStream(Toks, true, |
2221 | false); |
2222 | } else { |
2223 | MutableArrayRef<Token> Toks( |
2224 | PP.getPreprocessorAllocator().Allocate<Token>(2), 2); |
2225 | Token &pragmaUnusedTok = Toks[0]; |
2226 | pragmaUnusedTok.startToken(); |
2227 | pragmaUnusedTok.setKind(tok::annot_pragma_weak); |
2228 | pragmaUnusedTok.setLocation(WeakLoc); |
2229 | pragmaUnusedTok.setAnnotationEndLoc(WeakLoc); |
2230 | Toks[1] = WeakName; |
2231 | PP.EnterTokenStream(Toks, true, |
2232 | false); |
2233 | } |
2234 | } |
2235 | |
2236 | |
2237 | void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP, |
2238 | PragmaIntroducer Introducer, |
2239 | Token &RedefToken) { |
2240 | SourceLocation RedefLoc = RedefToken.getLocation(); |
2241 | |
2242 | Token Tok; |
2243 | PP.Lex(Tok); |
2244 | if (Tok.isNot(tok::identifier)) { |
2245 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << |
2246 | "redefine_extname"; |
2247 | return; |
2248 | } |
2249 | |
2250 | Token RedefName = Tok; |
2251 | PP.Lex(Tok); |
2252 | |
2253 | if (Tok.isNot(tok::identifier)) { |
2254 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) |
2255 | << "redefine_extname"; |
2256 | return; |
2257 | } |
2258 | |
2259 | Token AliasName = Tok; |
2260 | PP.Lex(Tok); |
2261 | |
2262 | if (Tok.isNot(tok::eod)) { |
2263 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << |
2264 | "redefine_extname"; |
2265 | return; |
2266 | } |
2267 | |
2268 | MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3), |
2269 | 3); |
2270 | Token &pragmaRedefTok = Toks[0]; |
2271 | pragmaRedefTok.startToken(); |
2272 | pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname); |
2273 | pragmaRedefTok.setLocation(RedefLoc); |
2274 | pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation()); |
2275 | Toks[1] = RedefName; |
2276 | Toks[2] = AliasName; |
2277 | PP.EnterTokenStream(Toks, true, |
2278 | false); |
2279 | } |
2280 | |
2281 | void PragmaFPContractHandler::HandlePragma(Preprocessor &PP, |
2282 | PragmaIntroducer Introducer, |
2283 | Token &Tok) { |
2284 | tok::OnOffSwitch OOS; |
2285 | if (PP.LexOnOffSwitch(OOS)) |
2286 | return; |
2287 | |
2288 | MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), |
2289 | 1); |
2290 | Toks[0].startToken(); |
2291 | Toks[0].setKind(tok::annot_pragma_fp_contract); |
2292 | Toks[0].setLocation(Tok.getLocation()); |
2293 | Toks[0].setAnnotationEndLoc(Tok.getLocation()); |
2294 | Toks[0].setAnnotationValue(reinterpret_cast<void*>( |
2295 | static_cast<uintptr_t>(OOS))); |
2296 | PP.EnterTokenStream(Toks, true, |
2297 | false); |
2298 | } |
2299 | |
2300 | void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, |
2301 | PragmaIntroducer Introducer, |
2302 | Token &Tok) { |
2303 | PP.LexUnexpandedToken(Tok); |
2304 | if (Tok.isNot(tok::identifier)) { |
2305 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << |
2306 | "OPENCL"; |
2307 | return; |
2308 | } |
2309 | IdentifierInfo *Ext = Tok.getIdentifierInfo(); |
2310 | SourceLocation NameLoc = Tok.getLocation(); |
2311 | |
2312 | PP.Lex(Tok); |
2313 | if (Tok.isNot(tok::colon)) { |
2314 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext; |
2315 | return; |
2316 | } |
2317 | |
2318 | PP.Lex(Tok); |
2319 | if (Tok.isNot(tok::identifier)) { |
2320 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0; |
2321 | return; |
2322 | } |
2323 | IdentifierInfo *Pred = Tok.getIdentifierInfo(); |
2324 | |
2325 | OpenCLExtState State; |
2326 | if (Pred->isStr("enable")) { |
2327 | State = Enable; |
2328 | } else if (Pred->isStr("disable")) { |
2329 | State = Disable; |
2330 | } else if (Pred->isStr("begin")) |
2331 | State = Begin; |
2332 | else if (Pred->isStr("end")) |
2333 | State = End; |
2334 | else { |
2335 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) |
2336 | << Ext->isStr("all"); |
2337 | return; |
2338 | } |
2339 | SourceLocation StateLoc = Tok.getLocation(); |
2340 | |
2341 | PP.Lex(Tok); |
2342 | if (Tok.isNot(tok::eod)) { |
2343 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << |
2344 | "OPENCL EXTENSION"; |
2345 | return; |
2346 | } |
2347 | |
2348 | auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1); |
2349 | Info->first = Ext; |
2350 | Info->second = State; |
2351 | MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), |
2352 | 1); |
2353 | Toks[0].startToken(); |
2354 | Toks[0].setKind(tok::annot_pragma_opencl_extension); |
2355 | Toks[0].setLocation(NameLoc); |
2356 | Toks[0].setAnnotationValue(static_cast<void*>(Info)); |
2357 | Toks[0].setAnnotationEndLoc(StateLoc); |
2358 | PP.EnterTokenStream(Toks, true, |
2359 | false); |
2360 | |
2361 | if (PP.getPPCallbacks()) |
2362 | PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext, |
2363 | StateLoc, State); |
2364 | } |
2365 | |
2366 | |
2367 | |
2368 | void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, |
2369 | PragmaIntroducer Introducer, |
2370 | Token &FirstTok) { |
2371 | if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored, |
2372 | FirstTok.getLocation())) { |
2373 | PP.Diag(FirstTok, diag::warn_pragma_omp_ignored); |
2374 | PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored, |
2375 | diag::Severity::Ignored, SourceLocation()); |
2376 | } |
2377 | PP.DiscardUntilEndOfDirective(); |
2378 | } |
2379 | |
2380 | |
2381 | |
2382 | void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, |
2383 | PragmaIntroducer Introducer, |
2384 | Token &FirstTok) { |
2385 | SmallVector<Token, 16> Pragma; |
2386 | Token Tok; |
2387 | Tok.startToken(); |
2388 | Tok.setKind(tok::annot_pragma_openmp); |
2389 | Tok.setLocation(Introducer.Loc); |
2390 | |
2391 | while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) { |
2392 | Pragma.push_back(Tok); |
2393 | PP.Lex(Tok); |
2394 | if (Tok.is(tok::annot_pragma_openmp)) { |
2395 | PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0; |
2396 | unsigned InnerPragmaCnt = 1; |
2397 | while (InnerPragmaCnt != 0) { |
2398 | PP.Lex(Tok); |
2399 | if (Tok.is(tok::annot_pragma_openmp)) |
2400 | ++InnerPragmaCnt; |
2401 | else if (Tok.is(tok::annot_pragma_openmp_end)) |
2402 | --InnerPragmaCnt; |
2403 | } |
2404 | PP.Lex(Tok); |
2405 | } |
2406 | } |
2407 | SourceLocation EodLoc = Tok.getLocation(); |
2408 | Tok.startToken(); |
2409 | Tok.setKind(tok::annot_pragma_openmp_end); |
2410 | Tok.setLocation(EodLoc); |
2411 | Pragma.push_back(Tok); |
2412 | |
2413 | auto Toks = std::make_unique<Token[]>(Pragma.size()); |
2414 | std::copy(Pragma.begin(), Pragma.end(), Toks.get()); |
2415 | PP.EnterTokenStream(std::move(Toks), Pragma.size(), |
2416 | false, false); |
2417 | } |
2418 | |
2419 | |
2420 | |
2421 | |
2422 | |
2423 | |
2424 | |
2425 | |
2426 | |
2427 | void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, |
2428 | PragmaIntroducer Introducer, |
2429 | Token &Tok) { |
2430 | SourceLocation PointersToMembersLoc = Tok.getLocation(); |
2431 | PP.Lex(Tok); |
2432 | if (Tok.isNot(tok::l_paren)) { |
2433 | PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen) |
2434 | << "pointers_to_members"; |
2435 | return; |
2436 | } |
2437 | PP.Lex(Tok); |
2438 | const IdentifierInfo *Arg = Tok.getIdentifierInfo(); |
2439 | if (!Arg) { |
2440 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) |
2441 | << "pointers_to_members"; |
2442 | return; |
2443 | } |
2444 | PP.Lex(Tok); |
2445 | |
2446 | LangOptions::PragmaMSPointersToMembersKind RepresentationMethod; |
2447 | if (Arg->isStr("best_case")) { |
2448 | RepresentationMethod = LangOptions::PPTMK_BestCase; |
2449 | } else { |
2450 | if (Arg->isStr("full_generality")) { |
2451 | if (Tok.is(tok::comma)) { |
2452 | PP.Lex(Tok); |
2453 | |
2454 | Arg = Tok.getIdentifierInfo(); |
2455 | if (!Arg) { |
2456 | PP.Diag(Tok.getLocation(), |
2457 | diag::err_pragma_pointers_to_members_unknown_kind) |
2458 | << Tok.getKind() << 0; |
2459 | return; |
2460 | } |
2461 | PP.Lex(Tok); |
2462 | } else if (Tok.is(tok::r_paren)) { |
2463 | |
2464 | |
2465 | Arg = nullptr; |
2466 | RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance; |
2467 | } else { |
2468 | PP.Diag(Tok.getLocation(), diag::err_expected_punc) |
2469 | << "full_generality"; |
2470 | return; |
2471 | } |
2472 | } |
2473 | |
2474 | if (Arg) { |
2475 | if (Arg->isStr("single_inheritance")) { |
2476 | RepresentationMethod = |
2477 | LangOptions::PPTMK_FullGeneralitySingleInheritance; |
2478 | } else if (Arg->isStr("multiple_inheritance")) { |
2479 | RepresentationMethod = |
2480 | LangOptions::PPTMK_FullGeneralityMultipleInheritance; |
2481 | } else if (Arg->isStr("virtual_inheritance")) { |
2482 | RepresentationMethod = |
2483 | LangOptions::PPTMK_FullGeneralityVirtualInheritance; |
2484 | } else { |
2485 | PP.Diag(Tok.getLocation(), |
2486 | diag::err_pragma_pointers_to_members_unknown_kind) |
2487 | << Arg << 1; |
2488 | return; |
2489 | } |
2490 | } |
2491 | } |
2492 | |
2493 | if (Tok.isNot(tok::r_paren)) { |
2494 | PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after) |
2495 | << (Arg ? Arg->getName() : "full_generality"); |
2496 | return; |
2497 | } |
2498 | |
2499 | SourceLocation EndLoc = Tok.getLocation(); |
2500 | PP.Lex(Tok); |
2501 | if (Tok.isNot(tok::eod)) { |
2502 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
2503 | << "pointers_to_members"; |
2504 | return; |
2505 | } |
2506 | |
2507 | Token AnnotTok; |
2508 | AnnotTok.startToken(); |
2509 | AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members); |
2510 | AnnotTok.setLocation(PointersToMembersLoc); |
2511 | AnnotTok.setAnnotationEndLoc(EndLoc); |
2512 | AnnotTok.setAnnotationValue( |
2513 | reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod))); |
2514 | PP.EnterToken(AnnotTok, true); |
2515 | } |
2516 | |
2517 | |
2518 | |
2519 | |
2520 | |
2521 | |
2522 | |
2523 | |
2524 | |
2525 | void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, |
2526 | PragmaIntroducer Introducer, Token &Tok) { |
2527 | SourceLocation VtorDispLoc = Tok.getLocation(); |
2528 | PP.Lex(Tok); |
2529 | if (Tok.isNot(tok::l_paren)) { |
2530 | PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp"; |
2531 | return; |
2532 | } |
2533 | PP.Lex(Tok); |
2534 | |
2535 | Sema::PragmaMsStackAction Action = Sema::PSK_Set; |
2536 | const IdentifierInfo *II = Tok.getIdentifierInfo(); |
2537 | if (II) { |
2538 | if (II->isStr("push")) { |
2539 | |
2540 | PP.Lex(Tok); |
2541 | if (Tok.isNot(tok::comma)) { |
2542 | PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp"; |
2543 | return; |
2544 | } |
2545 | PP.Lex(Tok); |
2546 | Action = Sema::PSK_Push_Set; |
2547 | |
2548 | } else if (II->isStr("pop")) { |
2549 | |
2550 | PP.Lex(Tok); |
2551 | Action = Sema::PSK_Pop; |
2552 | } |
2553 | |
2554 | } else { |
2555 | if (Tok.is(tok::r_paren)) { |
2556 | |
2557 | Action = Sema::PSK_Reset; |
2558 | } |
2559 | } |
2560 | |
2561 | |
2562 | uint64_t Value = 0; |
2563 | if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) { |
2564 | const IdentifierInfo *II = Tok.getIdentifierInfo(); |
2565 | if (II && II->isStr("off")) { |
2566 | PP.Lex(Tok); |
2567 | Value = 0; |
2568 | } else if (II && II->isStr("on")) { |
2569 | PP.Lex(Tok); |
2570 | Value = 1; |
2571 | } else if (Tok.is(tok::numeric_constant) && |
2572 | PP.parseSimpleIntegerLiteral(Tok, Value)) { |
2573 | if (Value > 2) { |
2574 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer) |
2575 | << 0 << 2 << "vtordisp"; |
2576 | return; |
2577 | } |
2578 | } else { |
2579 | PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) |
2580 | << "vtordisp"; |
2581 | return; |
2582 | } |
2583 | } |
2584 | |
2585 | |
2586 | if (Tok.isNot(tok::r_paren)) { |
2587 | PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp"; |
2588 | return; |
2589 | } |
2590 | SourceLocation EndLoc = Tok.getLocation(); |
2591 | PP.Lex(Tok); |
2592 | if (Tok.isNot(tok::eod)) { |
2593 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
2594 | << "vtordisp"; |
2595 | return; |
2596 | } |
2597 | |
2598 | |
2599 | Token AnnotTok; |
2600 | AnnotTok.startToken(); |
2601 | AnnotTok.setKind(tok::annot_pragma_ms_vtordisp); |
2602 | AnnotTok.setLocation(VtorDispLoc); |
2603 | AnnotTok.setAnnotationEndLoc(EndLoc); |
2604 | AnnotTok.setAnnotationValue(reinterpret_cast<void *>( |
2605 | static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF)))); |
2606 | PP.EnterToken(AnnotTok, false); |
2607 | } |
2608 | |
2609 | |
2610 | |
2611 | void PragmaMSPragma::HandlePragma(Preprocessor &PP, |
2612 | PragmaIntroducer Introducer, Token &Tok) { |
2613 | Token EoF, AnnotTok; |
2614 | EoF.startToken(); |
2615 | EoF.setKind(tok::eof); |
2616 | AnnotTok.startToken(); |
2617 | AnnotTok.setKind(tok::annot_pragma_ms_pragma); |
2618 | AnnotTok.setLocation(Tok.getLocation()); |
2619 | AnnotTok.setAnnotationEndLoc(Tok.getLocation()); |
2620 | SmallVector<Token, 8> TokenVector; |
2621 | |
2622 | for (; Tok.isNot(tok::eod); PP.Lex(Tok)) { |
2623 | TokenVector.push_back(Tok); |
2624 | AnnotTok.setAnnotationEndLoc(Tok.getLocation()); |
2625 | } |
2626 | |
2627 | TokenVector.push_back(EoF); |
2628 | |
2629 | |
2630 | markAsReinjectedForRelexing(TokenVector); |
2631 | auto TokenArray = std::make_unique<Token[]>(TokenVector.size()); |
2632 | std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get()); |
2633 | auto Value = new (PP.getPreprocessorAllocator()) |
2634 | std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray), |
2635 | TokenVector.size()); |
2636 | AnnotTok.setAnnotationValue(Value); |
2637 | PP.EnterToken(AnnotTok, false); |
2638 | } |
2639 | |
2640 | |
2641 | |
2642 | |
2643 | |
2644 | |
2645 | |
2646 | |
2647 | |
2648 | |
2649 | |
2650 | |
2651 | void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP, |
2652 | PragmaIntroducer Introducer, |
2653 | Token &Tok) { |
2654 | Sema::PragmaMsStackAction Action = Sema::PSK_Set; |
2655 | SourceLocation FloatControlLoc = Tok.getLocation(); |
2656 | Token PragmaName = Tok; |
2657 | if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) { |
2658 | PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored) |
2659 | << PragmaName.getIdentifierInfo()->getName(); |
2660 | return; |
2661 | } |
2662 | PP.Lex(Tok); |
2663 | if (Tok.isNot(tok::l_paren)) { |
2664 | PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren; |
2665 | return; |
2666 | } |
2667 | |
2668 | |
2669 | PP.Lex(Tok); |
2670 | if (Tok.isNot(tok::identifier)) { |
2671 | PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); |
2672 | return; |
2673 | } |
2674 | |
2675 | |
2676 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
2677 | PragmaFloatControlKind Kind = |
2678 | llvm::StringSwitch<PragmaFloatControlKind>(II->getName()) |
2679 | .Case("precise", PFC_Precise) |
2680 | .Case("except", PFC_Except) |
2681 | .Case("push", PFC_Push) |
2682 | .Case("pop", PFC_Pop) |
2683 | .Default(PFC_Unknown); |
2684 | PP.Lex(Tok); |
2685 | if (Kind == PFC_Unknown) { |
2686 | PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); |
2687 | return; |
2688 | } else if (Kind == PFC_Push || Kind == PFC_Pop) { |
2689 | if (Tok.isNot(tok::r_paren)) { |
2690 | PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); |
2691 | return; |
2692 | } |
2693 | PP.Lex(Tok); |
2694 | Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push; |
2695 | } else { |
2696 | if (Tok.is(tok::r_paren)) |
2697 | |
2698 | PP.Lex(Tok); |
2699 | else if (Tok.isNot(tok::comma)) { |
2700 | PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); |
2701 | return; |
2702 | } else { |
2703 | PP.Lex(Tok); |
2704 | if (!Tok.isAnyIdentifier()) { |
2705 | PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); |
2706 | return; |
2707 | } |
2708 | StringRef PushOnOff = Tok.getIdentifierInfo()->getName(); |
2709 | if (PushOnOff == "on") |
2710 | |
2711 | ; |
2712 | else if (PushOnOff == "off") { |
2713 | if (Kind == PFC_Precise) |
2714 | Kind = PFC_NoPrecise; |
2715 | if (Kind == PFC_Except) |
2716 | Kind = PFC_NoExcept; |
2717 | } else if (PushOnOff == "push") { |
2718 | Action = Sema::PSK_Push_Set; |
2719 | } else { |
2720 | PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); |
2721 | return; |
2722 | } |
2723 | PP.Lex(Tok); |
2724 | if (Tok.is(tok::comma)) { |
2725 | PP.Lex(Tok); |
2726 | if (!Tok.isAnyIdentifier()) { |
2727 | PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); |
2728 | return; |
2729 | } |
2730 | StringRef ExpectedPush = Tok.getIdentifierInfo()->getName(); |
2731 | if (ExpectedPush == "push") { |
2732 | Action = Sema::PSK_Push_Set; |
2733 | } else { |
2734 | PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); |
2735 | return; |
2736 | } |
2737 | PP.Lex(Tok); |
2738 | } |
2739 | if (Tok.isNot(tok::r_paren)) { |
2740 | PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed); |
2741 | return; |
2742 | } |
2743 | PP.Lex(Tok); |
2744 | } |
2745 | } |
2746 | SourceLocation EndLoc = Tok.getLocation(); |
2747 | if (Tok.isNot(tok::eod)) { |
2748 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
2749 | << "float_control"; |
2750 | return; |
2751 | } |
2752 | |
2753 | |
2754 | |
2755 | |
2756 | auto TokenArray = std::make_unique<Token[]>(1); |
2757 | TokenArray[0].startToken(); |
2758 | TokenArray[0].setKind(tok::annot_pragma_float_control); |
2759 | TokenArray[0].setLocation(FloatControlLoc); |
2760 | TokenArray[0].setAnnotationEndLoc(EndLoc); |
2761 | |
2762 | |
2763 | TokenArray[0].setAnnotationValue(reinterpret_cast<void *>( |
2764 | static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF)))); |
2765 | PP.EnterTokenStream(std::move(TokenArray), 1, |
2766 | false, false); |
2767 | } |
2768 | |
2769 | |
2770 | |
2771 | |
2772 | |
2773 | |
2774 | |
2775 | |
2776 | |
2777 | |
2778 | |
2779 | void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, |
2780 | PragmaIntroducer Introducer, |
2781 | Token &Tok) { |
2782 | SourceLocation DetectMismatchLoc = Tok.getLocation(); |
2783 | PP.Lex(Tok); |
2784 | if (Tok.isNot(tok::l_paren)) { |
2785 | PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren; |
2786 | return; |
2787 | } |
2788 | |
2789 | |
2790 | std::string NameString; |
2791 | if (!PP.LexStringLiteral(Tok, NameString, |
2792 | "pragma detect_mismatch", |
2793 | true)) |
2794 | return; |
2795 | |
2796 | |
2797 | std::string ValueString; |
2798 | if (Tok.isNot(tok::comma)) { |
2799 | PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); |
2800 | return; |
2801 | } |
2802 | |
2803 | if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch", |
2804 | true)) |
2805 | return; |
2806 | |
2807 | if (Tok.isNot(tok::r_paren)) { |
2808 | PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; |
2809 | return; |
2810 | } |
2811 | PP.Lex(Tok); |
2812 | |
2813 | if (Tok.isNot(tok::eod)) { |
2814 | PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); |
2815 | return; |
2816 | } |
2817 | |
2818 | |
2819 | if (PP.getPPCallbacks()) |
2820 | PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString, |
2821 | ValueString); |
2822 | |
2823 | Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString); |
2824 | } |
2825 | |
2826 | |
2827 | |
2828 | |
2829 | |
2830 | |
2831 | |
2832 | |
2833 | |
2834 | |
2835 | void PragmaCommentHandler::HandlePragma(Preprocessor &PP, |
2836 | PragmaIntroducer Introducer, |
2837 | Token &Tok) { |
2838 | SourceLocation CommentLoc = Tok.getLocation(); |
2839 | PP.Lex(Tok); |
2840 | if (Tok.isNot(tok::l_paren)) { |
2841 | PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); |
2842 | return; |
2843 | } |
2844 | |
2845 | |
2846 | PP.Lex(Tok); |
2847 | if (Tok.isNot(tok::identifier)) { |
2848 | PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); |
2849 | return; |
2850 | } |
2851 | |
2852 | |
2853 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
2854 | PragmaMSCommentKind Kind = |
2855 | llvm::StringSwitch<PragmaMSCommentKind>(II->getName()) |
2856 | .Case("linker", PCK_Linker) |
2857 | .Case("lib", PCK_Lib) |
2858 | .Case("compiler", PCK_Compiler) |
2859 | .Case("exestr", PCK_ExeStr) |
2860 | .Case("user", PCK_User) |
2861 | .Default(PCK_Unknown); |
2862 | if (Kind == PCK_Unknown) { |
2863 | PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); |
2864 | return; |
2865 | } |
2866 | |
2867 | if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) { |
2868 | PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored) |
2869 | << II->getName(); |
2870 | return; |
2871 | } |
2872 | |
2873 | |
2874 | |
2875 | if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) { |
2876 | PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored) |
2877 | << II->getName(); |
2878 | return; |
2879 | } |
2880 | |
2881 | |
2882 | PP.Lex(Tok); |
2883 | std::string ArgumentString; |
2884 | if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString, |
2885 | "pragma comment", |
2886 | true)) |
2887 | return; |
2888 | |
2889 | |
2890 | |
2891 | |
2892 | |
2893 | |
2894 | |
2895 | |
2896 | if (Tok.isNot(tok::r_paren)) { |
2897 | PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); |
2898 | return; |
2899 | } |
2900 | PP.Lex(Tok); |
2901 | |
2902 | if (Tok.isNot(tok::eod)) { |
2903 | PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); |
2904 | return; |
2905 | } |
2906 | |
2907 | |
2908 | if (PP.getPPCallbacks()) |
2909 | PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString); |
2910 | |
2911 | Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString); |
2912 | } |
2913 | |
2914 | |
2915 | |
2916 | void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP, |
2917 | PragmaIntroducer Introducer, |
2918 | Token &FirstToken) { |
2919 | Token Tok; |
2920 | PP.Lex(Tok); |
2921 | if (Tok.is(tok::eod)) { |
2922 | PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) |
2923 | << "clang optimize" << true << "'on' or 'off'"; |
2924 | return; |
2925 | } |
2926 | if (Tok.isNot(tok::identifier)) { |
2927 | PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) |
2928 | << PP.getSpelling(Tok); |
2929 | return; |
2930 | } |
2931 | const IdentifierInfo *II = Tok.getIdentifierInfo(); |
2932 | |
2933 | bool IsOn = false; |
2934 | if (II->isStr("on")) { |
2935 | IsOn = true; |
2936 | } else if (!II->isStr("off")) { |
2937 | PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) |
2938 | << PP.getSpelling(Tok); |
2939 | return; |
2940 | } |
2941 | PP.Lex(Tok); |
2942 | |
2943 | if (Tok.isNot(tok::eod)) { |
2944 | PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument) |
2945 | << PP.getSpelling(Tok); |
2946 | return; |
2947 | } |
2948 | |
2949 | Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation()); |
2950 | } |
2951 | |
2952 | namespace { |
2953 | |
2954 | struct TokFPAnnotValue { |
2955 | enum FlagKinds { Contract, Reassociate, Exceptions }; |
2956 | enum FlagValues { On, Off, Fast }; |
2957 | |
2958 | llvm::Optional<LangOptions::FPModeKind> ContractValue; |
2959 | llvm::Optional<LangOptions::FPModeKind> ReassociateValue; |
2960 | llvm::Optional<LangOptions::FPExceptionModeKind> ExceptionsValue; |
2961 | }; |
2962 | } |
2963 | |
2964 | void PragmaFPHandler::HandlePragma(Preprocessor &PP, |
2965 | PragmaIntroducer Introducer, Token &Tok) { |
2966 | |
2967 | Token PragmaName = Tok; |
2968 | SmallVector<Token, 1> TokenList; |
2969 | |
2970 | PP.Lex(Tok); |
2971 | if (Tok.isNot(tok::identifier)) { |
2972 | PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option) |
2973 | << true << ""; |
2974 | return; |
2975 | } |
2976 | |
2977 | auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue; |
2978 | while (Tok.is(tok::identifier)) { |
2979 | IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); |
2980 | |
2981 | auto FlagKind = |
2982 | llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>( |
2983 | OptionInfo->getName()) |
2984 | .Case("contract", TokFPAnnotValue::Contract) |
2985 | .Case("reassociate", TokFPAnnotValue::Reassociate) |
2986 | .Case("exceptions", TokFPAnnotValue::Exceptions) |
2987 | .Default(None); |
2988 | if (!FlagKind) { |
2989 | PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option) |
2990 | << false << OptionInfo; |
2991 | return; |
2992 | } |
2993 | PP.Lex(Tok); |
2994 | |
2995 | |
2996 | if (Tok.isNot(tok::l_paren)) { |
2997 | PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; |
2998 | return; |
2999 | } |
3000 | PP.Lex(Tok); |
3001 | |
3002 | if (Tok.isNot(tok::identifier)) { |
3003 | PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) |
3004 | << PP.getSpelling(Tok) << OptionInfo->getName() |
3005 | << static_cast<int>(*FlagKind); |
3006 | return; |
3007 | } |
3008 | const IdentifierInfo *II = Tok.getIdentifierInfo(); |
3009 | |
3010 | if (FlagKind == TokFPAnnotValue::Contract) { |
3011 | AnnotValue->ContractValue = |
3012 | llvm::StringSwitch<llvm::Optional<LangOptions::FPModeKind>>( |
3013 | II->getName()) |
3014 | .Case("on", LangOptions::FPModeKind::FPM_On) |
3015 | .Case("off", LangOptions::FPModeKind::FPM_Off) |
3016 | .Case("fast", LangOptions::FPModeKind::FPM_Fast) |
3017 | .Default(llvm::None); |
3018 | if (!AnnotValue->ContractValue) { |
3019 | PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) |
3020 | << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind; |
3021 | return; |
3022 | } |
3023 | } else if (FlagKind == TokFPAnnotValue::Reassociate) { |
3024 | AnnotValue->ReassociateValue = |
3025 | llvm::StringSwitch<llvm::Optional<LangOptions::FPModeKind>>( |
3026 | II->getName()) |
3027 | .Case("on", LangOptions::FPModeKind::FPM_On) |
3028 | .Case("off", LangOptions::FPModeKind::FPM_Off) |
3029 | .Default(llvm::None); |
3030 | if (!AnnotValue->ReassociateValue) { |
3031 | PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) |
3032 | << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind; |
3033 | return; |
3034 | } |
3035 | } else if (FlagKind == TokFPAnnotValue::Exceptions) { |
3036 | AnnotValue->ExceptionsValue = |
3037 | llvm::StringSwitch<llvm::Optional<LangOptions::FPExceptionModeKind>>( |
3038 | II->getName()) |
3039 | .Case("ignore", LangOptions::FPE_Ignore) |
3040 | .Case("maytrap", LangOptions::FPE_MayTrap) |
3041 | .Case("strict", LangOptions::FPE_Strict) |
3042 | .Default(llvm::None); |
3043 | if (!AnnotValue->ExceptionsValue) { |
3044 | PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) |
3045 | << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind; |
3046 | return; |
3047 | } |
3048 | } |
3049 | PP.Lex(Tok); |
3050 | |
3051 | |
3052 | if (Tok.isNot(tok::r_paren)) { |
3053 | PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; |
3054 | return; |
3055 | } |
3056 | PP.Lex(Tok); |
3057 | } |
3058 | |
3059 | if (Tok.isNot(tok::eod)) { |
3060 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
3061 | << "clang fp"; |
3062 | return; |
3063 | } |
3064 | |
3065 | Token FPTok; |
3066 | FPTok.startToken(); |
3067 | FPTok.setKind(tok::annot_pragma_fp); |
3068 | FPTok.setLocation(PragmaName.getLocation()); |
3069 | FPTok.setAnnotationEndLoc(PragmaName.getLocation()); |
3070 | FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue)); |
3071 | TokenList.push_back(FPTok); |
3072 | |
3073 | auto TokenArray = std::make_unique<Token[]>(TokenList.size()); |
3074 | std::copy(TokenList.begin(), TokenList.end(), TokenArray.get()); |
3075 | |
3076 | PP.EnterTokenStream(std::move(TokenArray), TokenList.size(), |
3077 | false, false); |
3078 | } |
3079 | |
3080 | void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP, |
3081 | PragmaIntroducer Introducer, |
3082 | Token &Tok) { |
3083 | Token PragmaName = Tok; |
3084 | SmallVector<Token, 1> TokenList; |
3085 | if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) { |
3086 | PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored) |
3087 | << PragmaName.getIdentifierInfo()->getName(); |
3088 | return; |
3089 | } |
3090 | |
3091 | PP.Lex(Tok); |
3092 | if (Tok.isNot(tok::identifier)) { |
3093 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) |
3094 | << PragmaName.getIdentifierInfo()->getName(); |
3095 | return; |
3096 | } |
3097 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
3098 | |
3099 | auto RM = |
3100 | llvm::StringSwitch<llvm::RoundingMode>(II->getName()) |
3101 | .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero) |
3102 | .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven) |
3103 | .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive) |
3104 | .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative) |
3105 | .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway) |
3106 | .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic) |
3107 | .Default(llvm::RoundingMode::Invalid); |
3108 | if (RM == llvm::RoundingMode::Invalid) { |
3109 | PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode); |
3110 | return; |
3111 | } |
3112 | PP.Lex(Tok); |
3113 | |
3114 | if (Tok.isNot(tok::eod)) { |
3115 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
3116 | << "STDC FENV_ROUND"; |
3117 | return; |
3118 | } |
3119 | |
3120 | |
3121 | PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported); |
3122 | |
3123 | MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), |
3124 | 1); |
3125 | Toks[0].startToken(); |
3126 | Toks[0].setKind(tok::annot_pragma_fenv_round); |
3127 | Toks[0].setLocation(Tok.getLocation()); |
3128 | Toks[0].setAnnotationEndLoc(Tok.getLocation()); |
3129 | Toks[0].setAnnotationValue( |
3130 | reinterpret_cast<void *>(static_cast<uintptr_t>(RM))); |
3131 | PP.EnterTokenStream(Toks, true, |
3132 | false); |
3133 | } |
3134 | |
3135 | void Parser::HandlePragmaFP() { |
3136 | assert(Tok.is(tok::annot_pragma_fp)); |
3137 | auto *AnnotValue = |
3138 | reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue()); |
3139 | |
3140 | if (AnnotValue->ReassociateValue) |
3141 | Actions.ActOnPragmaFPReassociate(Tok.getLocation(), |
3142 | *AnnotValue->ReassociateValue == |
3143 | LangOptions::FPModeKind::FPM_On); |
3144 | if (AnnotValue->ContractValue) |
3145 | Actions.ActOnPragmaFPContract(Tok.getLocation(), |
3146 | *AnnotValue->ContractValue); |
3147 | if (AnnotValue->ExceptionsValue) |
3148 | Actions.ActOnPragmaFPExceptions(Tok.getLocation(), |
3149 | *AnnotValue->ExceptionsValue); |
3150 | ConsumeAnnotationToken(); |
3151 | } |
3152 | |
3153 | |
3154 | static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, |
3155 | Token Option, bool ValueInParens, |
3156 | PragmaLoopHintInfo &Info) { |
3157 | SmallVector<Token, 1> ValueList; |
3158 | int OpenParens = ValueInParens ? 1 : 0; |
3159 | |
3160 | while (Tok.isNot(tok::eod)) { |
3161 | if (Tok.is(tok::l_paren)) |
3162 | OpenParens++; |
3163 | else if (Tok.is(tok::r_paren)) { |
3164 | OpenParens--; |
3165 | if (OpenParens == 0 && ValueInParens) |
3166 | break; |
3167 | } |
3168 | |
3169 | ValueList.push_back(Tok); |
3170 | PP.Lex(Tok); |
3171 | } |
3172 | |
3173 | if (ValueInParens) { |
3174 | |
3175 | if (Tok.isNot(tok::r_paren)) { |
3176 | PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; |
3177 | return true; |
3178 | } |
3179 | PP.Lex(Tok); |
3180 | } |
3181 | |
3182 | Token EOFTok; |
3183 | EOFTok.startToken(); |
3184 | EOFTok.setKind(tok::eof); |
3185 | EOFTok.setLocation(Tok.getLocation()); |
3186 | ValueList.push_back(EOFTok); |
3187 | |
3188 | markAsReinjectedForRelexing(ValueList); |
3189 | Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator()); |
3190 | |
3191 | Info.PragmaName = PragmaName; |
3192 | Info.Option = Option; |
3193 | return false; |
3194 | } |
3195 | |
3196 | |
3197 | |
3198 | |
3199 | |
3200 | |
3201 | |
3202 | |
3203 | |
3204 | |
3205 | |
3206 | |
3207 | |
3208 | |
3209 | |
3210 | |
3211 | |
3212 | |
3213 | |
3214 | |
3215 | |
3216 | |
3217 | |
3218 | |
3219 | |
3220 | |
3221 | |
3222 | |
3223 | |
3224 | |
3225 | |
3226 | |
3227 | |
3228 | |
3229 | |
3230 | |
3231 | |
3232 | |
3233 | |
3234 | |
3235 | |
3236 | |
3237 | |
3238 | |
3239 | |
3240 | |
3241 | |
3242 | |
3243 | |
3244 | void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, |
3245 | PragmaIntroducer Introducer, |
3246 | Token &Tok) { |
3247 | |
3248 | Token PragmaName = Tok; |
3249 | SmallVector<Token, 1> TokenList; |
3250 | |
3251 | |
3252 | PP.Lex(Tok); |
3253 | if (Tok.isNot(tok::identifier)) { |
3254 | PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) |
3255 | << true << ""; |
3256 | return; |
3257 | } |
3258 | |
3259 | while (Tok.is(tok::identifier)) { |
3260 | Token Option = Tok; |
3261 | IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); |
3262 | |
3263 | bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName()) |
3264 | .Case("vectorize", true) |
3265 | .Case("interleave", true) |
3266 | .Case("unroll", true) |
3267 | .Case("distribute", true) |
3268 | .Case("vectorize_predicate", true) |
3269 | .Case("vectorize_width", true) |
3270 | .Case("interleave_count", true) |
3271 | .Case("unroll_count", true) |
3272 | .Case("pipeline", true) |
3273 | .Case("pipeline_initiation_interval", true) |
3274 | .Default(false); |
3275 | if (!OptionValid) { |
3276 | PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) |
3277 | << false << OptionInfo; |
3278 | return; |
3279 | } |
3280 | PP.Lex(Tok); |
3281 | |
3282 | |
3283 | if (Tok.isNot(tok::l_paren)) { |
3284 | PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; |
3285 | return; |
3286 | } |
3287 | PP.Lex(Tok); |
3288 | |
3289 | auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; |
3290 | if (ParseLoopHintValue(PP, Tok, PragmaName, Option, true, |
3291 | *Info)) |
3292 | return; |
3293 | |
3294 | |
3295 | Token LoopHintTok; |
3296 | LoopHintTok.startToken(); |
3297 | LoopHintTok.setKind(tok::annot_pragma_loop_hint); |
3298 | LoopHintTok.setLocation(Introducer.Loc); |
3299 | LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation()); |
3300 | LoopHintTok.setAnnotationValue(static_cast<void *>(Info)); |
3301 | TokenList.push_back(LoopHintTok); |
3302 | } |
3303 | |
3304 | if (Tok.isNot(tok::eod)) { |
3305 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
3306 | << "clang loop"; |
3307 | return; |
3308 | } |
3309 | |
3310 | auto TokenArray = std::make_unique<Token[]>(TokenList.size()); |
3311 | std::copy(TokenList.begin(), TokenList.end(), TokenArray.get()); |
3312 | |
3313 | PP.EnterTokenStream(std::move(TokenArray), TokenList.size(), |
3314 | false, false); |
3315 | } |
3316 | |
3317 | |
3318 | |
3319 | |
3320 | |
3321 | |
3322 | |
3323 | |
3324 | |
3325 | |
3326 | |
3327 | |
3328 | |
3329 | |
3330 | |
3331 | |
3332 | |
3333 | |
3334 | |
3335 | |
3336 | |
3337 | |
3338 | void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, |
3339 | PragmaIntroducer Introducer, |
3340 | Token &Tok) { |
3341 | |
3342 | |
3343 | Token PragmaName = Tok; |
3344 | PP.Lex(Tok); |
3345 | auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; |
3346 | if (Tok.is(tok::eod)) { |
3347 | |
3348 | Info->PragmaName = PragmaName; |
3349 | Info->Option.startToken(); |
3350 | } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" || |
3351 | PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") { |
3352 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
3353 | << PragmaName.getIdentifierInfo()->getName(); |
3354 | return; |
3355 | } else { |
3356 | |
3357 | |
3358 | |
3359 | bool ValueInParens = Tok.is(tok::l_paren); |
3360 | if (ValueInParens) |
3361 | PP.Lex(Tok); |
3362 | |
3363 | Token Option; |
3364 | Option.startToken(); |
3365 | if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info)) |
3366 | return; |
3367 | |
3368 | |
3369 | |
3370 | if (PP.getLangOpts().CUDA && ValueInParens) |
3371 | PP.Diag(Info->Toks[0].getLocation(), |
3372 | diag::warn_pragma_unroll_cuda_value_in_parens); |
3373 | |
3374 | if (Tok.isNot(tok::eod)) { |
3375 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
3376 | << "unroll"; |
3377 | return; |
3378 | } |
3379 | } |
3380 | |
3381 | |
3382 | auto TokenArray = std::make_unique<Token[]>(1); |
3383 | TokenArray[0].startToken(); |
3384 | TokenArray[0].setKind(tok::annot_pragma_loop_hint); |
3385 | TokenArray[0].setLocation(Introducer.Loc); |
3386 | TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation()); |
3387 | TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); |
3388 | PP.EnterTokenStream(std::move(TokenArray), 1, |
3389 | false, false); |
3390 | } |
3391 | |
3392 | |
3393 | |
3394 | |
3395 | |
3396 | |
3397 | |
3398 | |
3399 | |
3400 | |
3401 | |
3402 | |
3403 | |
3404 | void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP, |
3405 | PragmaIntroducer Introducer, |
3406 | Token &Tok) { |
3407 | PP.Lex(Tok); |
3408 | |
3409 | if (Tok.isNot(tok::l_paren)) { |
3410 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) |
3411 | << "intrinsic"; |
3412 | return; |
3413 | } |
3414 | PP.Lex(Tok); |
3415 | |
3416 | bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H"); |
3417 | |
3418 | while (Tok.is(tok::identifier)) { |
3419 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
3420 | if (!II->getBuiltinID()) |
3421 | PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin) |
3422 | << II << SuggestIntrinH; |
3423 | |
3424 | PP.Lex(Tok); |
3425 | if (Tok.isNot(tok::comma)) |
3426 | break; |
3427 | PP.Lex(Tok); |
3428 | } |
3429 | |
3430 | if (Tok.isNot(tok::r_paren)) { |
3431 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) |
3432 | << "intrinsic"; |
3433 | return; |
3434 | } |
3435 | PP.Lex(Tok); |
3436 | |
3437 | if (Tok.isNot(tok::eod)) |
3438 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
3439 | << "intrinsic"; |
3440 | } |
3441 | |
3442 | |
3443 | void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP, |
3444 | PragmaIntroducer Introducer, |
3445 | Token &Tok) { |
3446 | SourceLocation StartLoc = Tok.getLocation(); |
3447 | PP.Lex(Tok); |
3448 | |
3449 | if (Tok.isNot(tok::l_paren)) { |
3450 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize"; |
3451 | return; |
3452 | } |
3453 | PP.Lex(Tok); |
3454 | |
3455 | if (Tok.isNot(tok::string_literal)) { |
3456 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize"; |
3457 | return; |
3458 | } |
3459 | |
3460 | PP.Lex(Tok); |
3461 | |
3462 | if (Tok.isNot(tok::comma)) { |
3463 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize"; |
3464 | return; |
3465 | } |
3466 | PP.Lex(Tok); |
3467 | |
3468 | if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) { |
3469 | PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument) |
3470 | << "optimize" << true << "'on' or 'off'"; |
3471 | return; |
3472 | } |
3473 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
3474 | if (!II || (!II->isStr("on") && !II->isStr("off"))) { |
3475 | PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument) |
3476 | << PP.getSpelling(Tok) << "optimize" << true |
3477 | << "'on' or 'off'"; |
3478 | return; |
3479 | } |
3480 | PP.Lex(Tok); |
3481 | |
3482 | if (Tok.isNot(tok::r_paren)) { |
3483 | PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize"; |
3484 | return; |
3485 | } |
3486 | PP.Lex(Tok); |
3487 | |
3488 | if (Tok.isNot(tok::eod)) { |
3489 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
3490 | << "optimize"; |
3491 | return; |
3492 | } |
3493 | PP.Diag(StartLoc, diag::warn_pragma_optimize); |
3494 | } |
3495 | |
3496 | void PragmaForceCUDAHostDeviceHandler::HandlePragma( |
3497 | Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) { |
3498 | Token FirstTok = Tok; |
3499 | |
3500 | PP.Lex(Tok); |
3501 | IdentifierInfo *Info = Tok.getIdentifierInfo(); |
3502 | if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) { |
3503 | PP.Diag(FirstTok.getLocation(), |
3504 | diag::warn_pragma_force_cuda_host_device_bad_arg); |
3505 | return; |
3506 | } |
3507 | |
3508 | if (Info->isStr("begin")) |
3509 | Actions.PushForceCUDAHostDevice(); |
3510 | else if (!Actions.PopForceCUDAHostDevice()) |
3511 | PP.Diag(FirstTok.getLocation(), |
3512 | diag::err_pragma_cannot_end_force_cuda_host_device); |
3513 | |
3514 | PP.Lex(Tok); |
3515 | if (!Tok.is(tok::eod)) |
3516 | PP.Diag(FirstTok.getLocation(), |
3517 | diag::warn_pragma_force_cuda_host_device_bad_arg); |
3518 | } |
3519 | |
3520 | |
3521 | |
3522 | |
3523 | |
3524 | |
3525 | |
3526 | |
3527 | |
3528 | |
3529 | |
3530 | |
3531 | |
3532 | |
3533 | |
3534 | |
3535 | |
3536 | |
3537 | |
3538 | |
3539 | |
3540 | |
3541 | |
3542 | |
3543 | |
3544 | |
3545 | |
3546 | |
3547 | void PragmaAttributeHandler::HandlePragma(Preprocessor &PP, |
3548 | PragmaIntroducer Introducer, |
3549 | Token &FirstToken) { |
3550 | Token Tok; |
3551 | PP.Lex(Tok); |
3552 | auto *Info = new (PP.getPreprocessorAllocator()) |
3553 | PragmaAttributeInfo(AttributesForPragmaAttribute); |
3554 | |
3555 | |
3556 | if (Tok.is(tok::identifier)) { |
3557 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
3558 | if (!II->isStr("push") && !II->isStr("pop")) { |
3559 | Info->Namespace = II; |
3560 | PP.Lex(Tok); |
3561 | |
3562 | if (!Tok.is(tok::period)) { |
3563 | PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period) |
3564 | << II; |
3565 | return; |
3566 | } |
3567 | PP.Lex(Tok); |
3568 | } |
3569 | } |
3570 | |
3571 | if (!Tok.isOneOf(tok::identifier, tok::l_paren)) { |
3572 | PP.Diag(Tok.getLocation(), |
3573 | diag::err_pragma_attribute_expected_push_pop_paren); |
3574 | return; |
3575 | } |
3576 | |
3577 | |
3578 | if (Tok.is(tok::l_paren)) { |
3579 | if (Info->Namespace) { |
3580 | PP.Diag(Tok.getLocation(), |
3581 | diag::err_pragma_attribute_namespace_on_attribute); |
3582 | PP.Diag(Tok.getLocation(), |
3583 | diag::note_pragma_attribute_namespace_on_attribute); |
3584 | return; |
3585 | } |
3586 | Info->Action = PragmaAttributeInfo::Attribute; |
3587 | } else { |
3588 | const IdentifierInfo *II = Tok.getIdentifierInfo(); |
3589 | if (II->isStr("push")) |
3590 | Info->Action = PragmaAttributeInfo::Push; |
3591 | else if (II->isStr("pop")) |
3592 | Info->Action = PragmaAttributeInfo::Pop; |
3593 | else { |
3594 | PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument) |
3595 | << PP.getSpelling(Tok); |
3596 | return; |
3597 | } |
3598 | |
3599 | PP.Lex(Tok); |
3600 | } |
3601 | |
3602 | |
3603 | if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) || |
3604 | Info->Action == PragmaAttributeInfo::Attribute) { |
3605 | if (Tok.isNot(tok::l_paren)) { |
3606 | PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; |
3607 | return; |
3608 | } |
3609 | PP.Lex(Tok); |
3610 | |
3611 | |
3612 | SmallVector<Token, 16> AttributeTokens; |
3613 | int OpenParens = 1; |
3614 | while (Tok.isNot(tok::eod)) { |
3615 | if (Tok.is(tok::l_paren)) |
3616 | OpenParens++; |
3617 | else if (Tok.is(tok::r_paren)) { |
3618 | OpenParens--; |
3619 | if (OpenParens == 0) |
3620 | break; |
3621 | } |
3622 | |
3623 | AttributeTokens.push_back(Tok); |
3624 | PP.Lex(Tok); |
3625 | } |
3626 | |
3627 | if (AttributeTokens.empty()) { |
3628 | PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute); |
3629 | return; |
3630 | } |
3631 | if (Tok.isNot(tok::r_paren)) { |
3632 | PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; |
3633 | return; |
3634 | } |
3635 | SourceLocation EndLoc = Tok.getLocation(); |
3636 | PP.Lex(Tok); |
3637 | |
3638 | |
3639 | Token EOFTok; |
3640 | EOFTok.startToken(); |
3641 | EOFTok.setKind(tok::eof); |
3642 | EOFTok.setLocation(EndLoc); |
3643 | AttributeTokens.push_back(EOFTok); |
3644 | |
3645 | markAsReinjectedForRelexing(AttributeTokens); |
3646 | Info->Tokens = |
3647 | llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator()); |
3648 | } |
3649 | |
3650 | if (Tok.isNot(tok::eod)) |
3651 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
3652 | << "clang attribute"; |
3653 | |
3654 | |
3655 | auto TokenArray = std::make_unique<Token[]>(1); |
3656 | TokenArray[0].startToken(); |
3657 | TokenArray[0].setKind(tok::annot_pragma_attribute); |
3658 | TokenArray[0].setLocation(FirstToken.getLocation()); |
3659 | TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation()); |
3660 | TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); |
3661 | PP.EnterTokenStream(std::move(TokenArray), 1, |
3662 | false, false); |
3663 | } |
3664 | |
3665 | |
3666 | void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP, |
3667 | PragmaIntroducer Introducer, |
3668 | Token &Tok) { |
3669 | PP.Lex(Tok); |
3670 | if (Tok.is(tok::eod)) { |
3671 | PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) |
3672 | << "clang max_tokens_here" << true << "integer"; |
3673 | return; |
3674 | } |
3675 | |
3676 | SourceLocation Loc = Tok.getLocation(); |
3677 | uint64_t MaxTokens; |
3678 | if (Tok.isNot(tok::numeric_constant) || |
3679 | !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) { |
3680 | PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer) |
3681 | << "clang max_tokens_here"; |
3682 | return; |
3683 | } |
3684 | |
3685 | if (Tok.isNot(tok::eod)) { |
3686 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
3687 | << "clang max_tokens_here"; |
3688 | return; |
3689 | } |
3690 | |
3691 | if (PP.getTokenCount() > MaxTokens) { |
3692 | PP.Diag(Loc, diag::warn_max_tokens) |
3693 | << PP.getTokenCount() << (unsigned)MaxTokens; |
3694 | } |
3695 | } |
3696 | |
3697 | |
3698 | void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP, |
3699 | PragmaIntroducer Introducer, |
3700 | Token &Tok) { |
3701 | PP.Lex(Tok); |
3702 | if (Tok.is(tok::eod)) { |
3703 | PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) |
3704 | << "clang max_tokens_total" << true << "integer"; |
3705 | return; |
3706 | } |
3707 | |
3708 | SourceLocation Loc = Tok.getLocation(); |
3709 | uint64_t MaxTokens; |
3710 | if (Tok.isNot(tok::numeric_constant) || |
3711 | !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) { |
3712 | PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer) |
3713 | << "clang max_tokens_total"; |
3714 | return; |
3715 | } |
3716 | |
3717 | if (Tok.isNot(tok::eod)) { |
3718 | PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) |
3719 | << "clang max_tokens_total"; |
3720 | return; |
3721 | } |
3722 | |
3723 | PP.overrideMaxTokens(MaxTokens, Loc); |
3724 | } |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_H |
15 | #define LLVM_CLANG_BASIC_DIAGNOSTIC_H |
16 | |
17 | #include "clang/Basic/DiagnosticIDs.h" |
18 | #include "clang/Basic/DiagnosticOptions.h" |
19 | #include "clang/Basic/SourceLocation.h" |
20 | #include "clang/Basic/Specifiers.h" |
21 | #include "llvm/ADT/ArrayRef.h" |
22 | #include "llvm/ADT/DenseMap.h" |
23 | #include "llvm/ADT/IntrusiveRefCntPtr.h" |
24 | #include "llvm/ADT/Optional.h" |
25 | #include "llvm/ADT/SmallVector.h" |
26 | #include "llvm/ADT/StringRef.h" |
27 | #include "llvm/ADT/iterator_range.h" |
28 | #include "llvm/Support/Compiler.h" |
29 | #include <cassert> |
30 | #include <cstdint> |
31 | #include <limits> |
32 | #include <list> |
33 | #include <map> |
34 | #include <memory> |
35 | #include <string> |
36 | #include <type_traits> |
37 | #include <utility> |
38 | #include <vector> |
39 | |
40 | namespace llvm { |
41 | class Error; |
42 | } |
43 | |
44 | namespace clang { |
45 | |
46 | class DeclContext; |
47 | class DiagnosticBuilder; |
48 | class DiagnosticConsumer; |
49 | class IdentifierInfo; |
50 | class LangOptions; |
51 | class Preprocessor; |
52 | class SourceManager; |
53 | class StoredDiagnostic; |
54 | |
55 | namespace tok { |
56 | |
57 | enum TokenKind : unsigned short; |
58 | |
59 | } |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | class FixItHint { |
71 | public: |
72 | |
73 | |
74 | CharSourceRange RemoveRange; |
75 | |
76 | |
77 | |
78 | CharSourceRange InsertFromRange; |
79 | |
80 | |
81 | |
82 | std::string CodeToInsert; |
83 | |
84 | bool BeforePreviousInsertions = false; |
85 | |
86 | |
87 | |
88 | FixItHint() = default; |
89 | |
90 | bool isNull() const { |
91 | return !RemoveRange.isValid(); |
92 | } |
93 | |
94 | |
95 | |
96 | static FixItHint CreateInsertion(SourceLocation InsertionLoc, |
97 | StringRef Code, |
98 | bool BeforePreviousInsertions = false) { |
99 | FixItHint Hint; |
100 | Hint.RemoveRange = |
101 | CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); |
102 | Hint.CodeToInsert = std::string(Code); |
103 | Hint.BeforePreviousInsertions = BeforePreviousInsertions; |
104 | return Hint; |
105 | } |
106 | |
107 | |
108 | |
109 | static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc, |
110 | CharSourceRange FromRange, |
111 | bool BeforePreviousInsertions = false) { |
112 | FixItHint Hint; |
113 | Hint.RemoveRange = |
114 | CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); |
115 | Hint.InsertFromRange = FromRange; |
116 | Hint.BeforePreviousInsertions = BeforePreviousInsertions; |
117 | return Hint; |
118 | } |
119 | |
120 | |
121 | |
122 | static FixItHint CreateRemoval(CharSourceRange RemoveRange) { |
123 | FixItHint Hint; |
124 | Hint.RemoveRange = RemoveRange; |
125 | return Hint; |
126 | } |
127 | static FixItHint CreateRemoval(SourceRange RemoveRange) { |
128 | return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange)); |
129 | } |
130 | |
131 | |
132 | |
133 | static FixItHint CreateReplacement(CharSourceRange RemoveRange, |
134 | StringRef Code) { |
135 | FixItHint Hint; |
136 | Hint.RemoveRange = RemoveRange; |
137 | Hint.CodeToInsert = std::string(Code); |
138 | return Hint; |
139 | } |
140 | |
141 | static FixItHint CreateReplacement(SourceRange RemoveRange, |
142 | StringRef Code) { |
143 | return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code); |
144 | } |
145 | }; |
146 | |
147 | struct DiagnosticStorage { |
148 | enum { |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | MaxArguments = 10 |
155 | }; |
156 | |
157 | |
158 | unsigned char NumDiagArgs = 0; |
159 | |
160 | |
161 | |
162 | unsigned char DiagArgumentsKind[MaxArguments]; |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | intptr_t DiagArgumentsVal[MaxArguments]; |
170 | |
171 | |
172 | |
173 | std::string DiagArgumentsStr[MaxArguments]; |
174 | |
175 | |
176 | SmallVector<CharSourceRange, 8> DiagRanges; |
177 | |
178 | |
179 | |
180 | SmallVector<FixItHint, 6> FixItHints; |
181 | |
182 | DiagnosticStorage() = default; |
183 | }; |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { |
192 | public: |
193 | |
194 | enum Level { |
195 | Ignored = DiagnosticIDs::Ignored, |
196 | Note = DiagnosticIDs::Note, |
197 | Remark = DiagnosticIDs::Remark, |
198 | Warning = DiagnosticIDs::Warning, |
199 | Error = DiagnosticIDs::Error, |
200 | Fatal = DiagnosticIDs::Fatal |
201 | }; |
202 | |
203 | enum ArgumentKind { |
204 | |
205 | ak_std_string, |
206 | |
207 | |
208 | ak_c_string, |
209 | |
210 | |
211 | ak_sint, |
212 | |
213 | |
214 | ak_uint, |
215 | |
216 | |
217 | ak_tokenkind, |
218 | |
219 | |
220 | ak_identifierinfo, |
221 | |
222 | |
223 | ak_addrspace, |
224 | |
225 | |
226 | ak_qual, |
227 | |
228 | |
229 | ak_qualtype, |
230 | |
231 | |
232 | ak_declarationname, |
233 | |
234 | |
235 | ak_nameddecl, |
236 | |
237 | |
238 | ak_nestednamespec, |
239 | |
240 | |
241 | ak_declcontext, |
242 | |
243 | |
244 | ak_qualtype_pair, |
245 | |
246 | |
247 | ak_attr |
248 | }; |
249 | |
250 | |
251 | |
252 | using ArgumentValue = std::pair<ArgumentKind, intptr_t>; |
253 | |
254 | private: |
255 | |
256 | unsigned char AllExtensionsSilenced = 0; |
257 | |
258 | |
259 | bool FatalsAsError = false; |
260 | |
261 | |
262 | bool SuppressAllDiagnostics = false; |
263 | |
264 | |
265 | bool ElideType = true; |
266 | |
267 | |
268 | bool PrintTemplateTree = false; |
269 | |
270 | |
271 | bool ShowColors = false; |
272 | |
273 | |
274 | OverloadsShown ShowOverloads = Ovl_All; |
275 | |
276 | |
277 | |
278 | |
279 | |
280 | |
281 | unsigned NumOverloadsToShow = 32; |
282 | |
283 | |
284 | unsigned ErrorLimit = 0; |
285 | |
286 | |
287 | unsigned TemplateBacktraceLimit = 0; |
288 | |
289 | |
290 | unsigned ConstexprBacktraceLimit = 0; |
291 | |
292 | IntrusiveRefCntPtr<DiagnosticIDs> Diags; |
293 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; |
294 | DiagnosticConsumer *Client = nullptr; |
295 | std::unique_ptr<DiagnosticConsumer> Owner; |
296 | SourceManager *SourceMgr = nullptr; |
297 | |
298 | |
299 | |
300 | |
301 | |
302 | |
303 | |
304 | |
305 | |
306 | |
307 | |
308 | |
309 | class DiagState { |
310 | llvm::DenseMap<unsigned, DiagnosticMapping> DiagMap; |
311 | |
312 | public: |
313 | |
314 | |
315 | |
316 | unsigned IgnoreAllWarnings : 1; |
317 | |
318 | |
319 | unsigned EnableAllWarnings : 1; |
320 | |
321 | |
322 | unsigned WarningsAsErrors : 1; |
323 | |
324 | |
325 | unsigned ErrorsAsFatal : 1; |
326 | |
327 | |
328 | unsigned SuppressSystemWarnings : 1; |
329 | |
330 | |
331 | diag::Severity ExtBehavior = diag::Severity::Ignored; |
332 | |
333 | DiagState() |
334 | : IgnoreAllWarnings(false), EnableAllWarnings(false), |
335 | WarningsAsErrors(false), ErrorsAsFatal(false), |
336 | SuppressSystemWarnings(false) {} |
337 | |
338 | using iterator = llvm::DenseMap<unsigned, DiagnosticMapping>::iterator; |
339 | using const_iterator = |
340 | llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator; |
341 | |
342 | void setMapping(diag::kind Diag, DiagnosticMapping Info) { |
343 | DiagMap[Diag] = Info; |
344 | } |
345 | |
346 | DiagnosticMapping lookupMapping(diag::kind Diag) const { |
347 | return DiagMap.lookup(Diag); |
348 | } |
349 | |
350 | DiagnosticMapping &getOrAddMapping(diag::kind Diag); |
351 | |
352 | const_iterator begin() const { return DiagMap.begin(); } |
353 | const_iterator end() const { return DiagMap.end(); } |
354 | }; |
355 | |
356 | |
357 | std::list<DiagState> DiagStates; |
358 | |
359 | |
360 | |
361 | class DiagStateMap { |
362 | public: |
363 | |
364 | void appendFirst(DiagState *State); |
365 | |
366 | |
367 | void append(SourceManager &SrcMgr, SourceLocation Loc, DiagState *State); |
368 | |
369 | |
370 | DiagState *lookup(SourceManager &SrcMgr, SourceLocation Loc) const; |
371 | |
372 | |
373 | bool empty() const { return Files.empty(); } |
374 | |
375 | |
376 | void clear() { |
377 | Files.clear(); |
378 | FirstDiagState = CurDiagState = nullptr; |
379 | CurDiagStateLoc = SourceLocation(); |
380 | } |
381 | |
382 | |
383 | LLVM_DUMP_METHOD void dump(SourceManager &SrcMgr, |
384 | StringRef DiagName = StringRef()) const; |
385 | |
386 | |
387 | DiagState *getCurDiagState() const { return CurDiagState; } |
388 | |
389 | |
390 | SourceLocation getCurDiagStateLoc() const { return CurDiagStateLoc; } |
391 | |
392 | private: |
393 | friend class ASTReader; |
394 | friend class ASTWriter; |
395 | |
396 | |
397 | |
398 | |
399 | |
400 | |
401 | struct DiagStatePoint { |
402 | DiagState *State; |
403 | unsigned Offset; |
404 | |
405 | DiagStatePoint(DiagState *State, unsigned Offset) |
406 | : State(State), Offset(Offset) {} |
407 | }; |
408 | |
409 | |
410 | |
411 | struct File { |
412 | |
413 | |
414 | |
415 | File *Parent = nullptr; |
416 | |
417 | |
418 | unsigned ParentOffset = 0; |
419 | |
420 | |
421 | |
422 | bool HasLocalTransitions = false; |
423 | |
424 | |
425 | |
426 | llvm::SmallVector<DiagStatePoint, 4> StateTransitions; |
427 | |
428 | DiagState *lookup(unsigned Offset) const; |
429 | }; |
430 | |
431 | |
432 | mutable std::map<FileID, File> Files; |
433 | |
434 | |
435 | DiagState *FirstDiagState; |
436 | |
437 | |
438 | DiagState *CurDiagState; |
439 | |
440 | |
441 | SourceLocation CurDiagStateLoc; |
442 | |
443 | |
444 | File *getFile(SourceManager &SrcMgr, FileID ID) const; |
445 | }; |
446 | |
447 | DiagStateMap DiagStatesByLoc; |
448 | |
449 | |
450 | |
451 | std::vector<DiagState *> DiagStateOnPushStack; |
452 | |
453 | DiagState *GetCurDiagState() const { |
454 | return DiagStatesByLoc.getCurDiagState(); |
455 | } |
456 | |
457 | void PushDiagStatePoint(DiagState *State, SourceLocation L); |
458 | |
459 | |
460 | |
461 | DiagState *GetDiagStateForLoc(SourceLocation Loc) const { |
462 | return SourceMgr ? DiagStatesByLoc.lookup(*SourceMgr, Loc) |
463 | : DiagStatesByLoc.getCurDiagState(); |
464 | } |
465 | |
466 | |
467 | bool ErrorOccurred; |
468 | |
469 | |
470 | |
471 | bool UncompilableErrorOccurred; |
472 | |
473 | |
474 | bool FatalErrorOccurred; |
475 | |
476 | |
477 | bool UnrecoverableErrorOccurred; |
478 | |
479 | |
480 | |
481 | unsigned TrapNumErrorsOccurred; |
482 | unsigned TrapNumUnrecoverableErrorsOccurred; |
483 | |
484 | |
485 | |
486 | |
487 | |
488 | DiagnosticIDs::Level LastDiagLevel; |
489 | |
490 | |
491 | unsigned NumWarnings; |
492 | |
493 | |
494 | unsigned NumErrors; |
495 | |
496 | |
497 | |
498 | |
499 | |
500 | |
501 | |
502 | |
503 | |
504 | |
505 | |
506 | using ArgToStringFnTy = void (*)( |
507 | ArgumentKind Kind, intptr_t Val, |
508 | StringRef Modifier, StringRef Argument, |
509 | ArrayRef<ArgumentValue> PrevArgs, |
510 | SmallVectorImpl<char> &Output, |
511 | void *Cookie, |
512 | ArrayRef<intptr_t> QualTypeVals); |
513 | |
514 | void *ArgToStringCookie = nullptr; |
515 | ArgToStringFnTy ArgToStringFn; |
516 | |
517 | |
518 | |
519 | |
520 | unsigned DelayedDiagID; |
521 | |
522 | |
523 | std::string DelayedDiagArg1; |
524 | |
525 | |
526 | std::string DelayedDiagArg2; |
527 | |
528 | |
529 | std::string DelayedDiagArg3; |
530 | |
531 | |
532 | |
533 | |
534 | |
535 | |
536 | std::string FlagValue; |
537 | |
538 | public: |
539 | explicit DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> Diags, |
540 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, |
541 | DiagnosticConsumer *client = nullptr, |
542 | bool ShouldOwnClient = true); |
543 | DiagnosticsEngine(const DiagnosticsEngine &) = delete; |
544 | DiagnosticsEngine &operator=(const DiagnosticsEngine &) = delete; |
545 | ~DiagnosticsEngine(); |
546 | |
547 | LLVM_DUMP_METHOD void dump() const; |
548 | LLVM_DUMP_METHOD void dump(StringRef DiagName) const; |
549 | |
550 | const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const { |
551 | return Diags; |
552 | } |
553 | |
554 | |
555 | DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; } |
556 | |
557 | using diag_mapping_range = llvm::iterator_range<DiagState::const_iterator>; |
558 | |
559 | |
560 | diag_mapping_range getDiagnosticMappings() const { |
561 | const DiagState &DS = *GetCurDiagState(); |
562 | return diag_mapping_range(DS.begin(), DS.end()); |
563 | } |
564 | |
565 | DiagnosticConsumer *getClient() { return Client; } |
566 | const DiagnosticConsumer *getClient() const { return Client; } |
567 | |
568 | |
569 | bool ownsClient() const { return Owner != nullptr; } |
570 | |
571 | |
572 | |
573 | std::unique_ptr<DiagnosticConsumer> takeClient() { return std::move(Owner); } |
574 | |
575 | bool hasSourceManager() const { return SourceMgr != nullptr; } |
576 | |
577 | SourceManager &getSourceManager() const { |
578 | assert(SourceMgr && "SourceManager not set!"); |
579 | return *SourceMgr; |
580 | } |
581 | |
582 | void setSourceManager(SourceManager *SrcMgr) { |
583 | assert(DiagStatesByLoc.empty() && |
584 | "Leftover diag state from a different SourceManager."); |
585 | SourceMgr = SrcMgr; |
586 | } |
587 | |
588 | |
589 | |
590 | |
591 | |
592 | |
593 | |
594 | |
595 | void pushMappings(SourceLocation Loc); |
596 | |
597 | |
598 | |
599 | |
600 | |
601 | |
602 | bool popMappings(SourceLocation Loc); |
603 | |
604 | |
605 | |
606 | |
607 | |
608 | void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true); |
609 | |
610 | |
611 | |
612 | |
613 | |
614 | void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; } |
615 | |
616 | |
617 | |
618 | void setTemplateBacktraceLimit(unsigned Limit) { |
619 | TemplateBacktraceLimit = Limit; |
620 | } |
621 | |
622 | |
623 | |
624 | unsigned getTemplateBacktraceLimit() const { |
625 | return TemplateBacktraceLimit; |
626 | } |
627 | |
628 | |
629 | |
630 | void setConstexprBacktraceLimit(unsigned Limit) { |
631 | ConstexprBacktraceLimit = Limit; |
632 | } |
633 | |
634 | |
635 | |
636 | unsigned getConstexprBacktraceLimit() const { |
637 | return ConstexprBacktraceLimit; |
638 | } |
639 | |
640 | |
641 | |
642 | |
643 | void setIgnoreAllWarnings(bool Val) { |
644 | GetCurDiagState()->IgnoreAllWarnings = Val; |
645 | } |
646 | bool getIgnoreAllWarnings() const { |
647 | return GetCurDiagState()->IgnoreAllWarnings; |
648 | } |
649 | |
650 | |
651 | |
652 | |
653 | |
654 | void setEnableAllWarnings(bool Val) { |
655 | GetCurDiagState()->EnableAllWarnings = Val; |
656 | } |
657 | bool getEnableAllWarnings() const { |
658 | return GetCurDiagState()->EnableAllWarnings; |
659 | } |
660 | |
661 | |
662 | void setWarningsAsErrors(bool Val) { |
663 | GetCurDiagState()->WarningsAsErrors = Val; |
664 | } |
665 | bool getWarningsAsErrors() const { |
666 | return GetCurDiagState()->WarningsAsErrors; |
667 | } |
668 | |
669 | |
670 | void setErrorsAsFatal(bool Val) { GetCurDiagState()->ErrorsAsFatal = Val; } |
671 | bool getErrorsAsFatal() const { return GetCurDiagState()->ErrorsAsFatal; } |
672 | |
673 | |
674 | |
675 | |
676 | void setFatalsAsError(bool Val) { FatalsAsError = Val; } |
677 | bool getFatalsAsError() const { return FatalsAsError; } |
678 | |
679 | |
680 | void setSuppressSystemWarnings(bool Val) { |
681 | GetCurDiagState()->SuppressSystemWarnings = Val; |
682 | } |
683 | bool getSuppressSystemWarnings() const { |
684 | return GetCurDiagState()->SuppressSystemWarnings; |
685 | } |
686 | |
687 | |
688 | |
689 | |
690 | void setSuppressAllDiagnostics(bool Val) { SuppressAllDiagnostics = Val; } |
691 | bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; } |
692 | |
693 | |
694 | |
695 | void setElideType(bool Val) { ElideType = Val; } |
696 | bool getElideType() { return ElideType; } |
697 | |
698 | |
699 | |
700 | void setPrintTemplateTree(bool Val) { PrintTemplateTree = Val; } |
701 | bool getPrintTemplateTree() { return PrintTemplateTree; } |
702 | |
703 | |
704 | |
705 | void setShowColors(bool Val) { ShowColors = Val; } |
706 | bool getShowColors() { return ShowColors; } |
707 | |
708 | |
709 | |
710 | |
711 | |
712 | void setShowOverloads(OverloadsShown Val) { |
713 | ShowOverloads = Val; |
714 | } |
715 | OverloadsShown getShowOverloads() const { return ShowOverloads; } |
716 | |
717 | |
718 | |
719 | |
720 | |
721 | |
722 | |
723 | |
724 | unsigned getNumOverloadCandidatesToShow() const { |
725 | switch (getShowOverloads()) { |
726 | case Ovl_All: |
727 | |
728 | |
729 | |
730 | return std::numeric_limits<int>::max(); |
731 | case Ovl_Best: |
732 | return NumOverloadsToShow; |
733 | } |
734 | llvm_unreachable("invalid OverloadsShown kind"); |
735 | } |
736 | |
737 | |
738 | |
739 | void overloadCandidatesShown(unsigned N) { |
740 | |
741 | |
742 | |
743 | if (N > 4) { |
744 | NumOverloadsToShow = 4; |
745 | } |
746 | } |
747 | |
748 | |
749 | |
750 | |
751 | |
752 | |
753 | |
754 | void setLastDiagnosticIgnored(bool Ignored) { |
755 | if (LastDiagLevel == DiagnosticIDs::Fatal) |
756 | FatalErrorOccurred = true; |
757 | LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning; |
758 | } |
759 | |
760 | |
761 | |
762 | |
763 | bool isLastDiagnosticIgnored() const { |
764 | return LastDiagLevel == DiagnosticIDs::Ignored; |
765 | } |
766 | |
767 | |
768 | |
769 | |
770 | |
771 | void setExtensionHandlingBehavior(diag::Severity H) { |
772 | GetCurDiagState()->ExtBehavior = H; |
773 | } |
774 | diag::Severity getExtensionHandlingBehavior() const { |
775 | return GetCurDiagState()->ExtBehavior; |
776 | } |
777 | |
778 | |
779 | |
780 | |
781 | |
782 | void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; } |
783 | void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; } |
784 | bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; } |
785 | |
786 | |
787 | |
788 | |
789 | |
790 | |
791 | |
792 | |
793 | |
794 | void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc); |
795 | |
796 | |
797 | |
798 | |
799 | |
800 | |
801 | |
802 | |
803 | |
804 | |
805 | |
806 | |
807 | bool setSeverityForGroup(diag::Flavor Flavor, StringRef Group, |
808 | diag::Severity Map, |
809 | SourceLocation Loc = SourceLocation()); |
810 | |
811 | |
812 | |
813 | |
814 | |
815 | |
816 | bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled); |
817 | |
818 | |
819 | |
820 | |
821 | |
822 | |
823 | bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled); |
824 | |
825 | |
826 | |
827 | |
828 | |
829 | |
830 | void setSeverityForAll(diag::Flavor Flavor, diag::Severity Map, |
831 | SourceLocation Loc = SourceLocation()); |
832 | |
833 | bool hasErrorOccurred() const { return ErrorOccurred; } |
834 | |
835 | |
836 | |
837 | bool hasUncompilableErrorOccurred() const { |
838 | return UncompilableErrorOccurred; |
839 | } |
840 | bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } |
841 | |
842 | |
843 | bool hasUnrecoverableErrorOccurred() const { |
844 | return FatalErrorOccurred || UnrecoverableErrorOccurred; |
845 | } |
846 | |
847 | unsigned getNumErrors() const { return NumErrors; } |
848 | unsigned getNumWarnings() const { return NumWarnings; } |
849 | |
850 | void setNumWarnings(unsigned NumWarnings) { |
851 | this->NumWarnings = NumWarnings; |
852 | } |
853 | |
854 | |
855 | |
856 | |
857 | |
858 | |
859 | |
860 | |
861 | |
862 | template <unsigned N> |
863 | unsigned getCustomDiagID(Level L, const char (&FormatString)[N]) { |
864 | return Diags->getCustomDiagID((DiagnosticIDs::Level)L, |
865 | StringRef(FormatString, N - 1)); |
866 | } |
867 | |
868 | |
869 | |
870 | void ConvertArgToString(ArgumentKind Kind, intptr_t Val, |
871 | StringRef Modifier, StringRef Argument, |
872 | ArrayRef<ArgumentValue> PrevArgs, |
873 | SmallVectorImpl<char> &Output, |
874 | ArrayRef<intptr_t> QualTypeVals) const { |
875 | ArgToStringFn(Kind, Val, Modifier, Argument, PrevArgs, Output, |
876 | ArgToStringCookie, QualTypeVals); |
877 | } |
878 | |
879 | void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) { |
880 | ArgToStringFn = Fn; |
881 | ArgToStringCookie = Cookie; |
882 | } |
883 | |
884 | |
885 | |
886 | void notePriorDiagnosticFrom(const DiagnosticsEngine &Other) { |
887 | LastDiagLevel = Other.LastDiagLevel; |
888 | } |
889 | |
890 | |
891 | |
892 | void Reset(); |
893 | |
894 | |
895 | |
896 | |
897 | |
898 | |
899 | |
900 | |
901 | |
902 | |
903 | |
904 | |
905 | |
906 | bool isIgnored(unsigned DiagID, SourceLocation Loc) const { |
907 | return Diags->getDiagnosticSeverity(DiagID, Loc, *this) == |
908 | diag::Severity::Ignored; |
909 | } |
910 | |
911 | |
912 | |
913 | |
914 | |
915 | |
916 | |
917 | |
918 | |
919 | |
920 | |
921 | Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const { |
922 | return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this); |
923 | } |
924 | |
925 | |
926 | |
927 | |
928 | |
929 | |
930 | |
931 | |
932 | |
933 | inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID); |
934 | inline DiagnosticBuilder Report(unsigned DiagID); |
935 | |
936 | void Report(const StoredDiagnostic &storedDiag); |
937 | |
938 | |
939 | bool isDiagnosticInFlight() const { |
940 | return CurDiagID != std::numeric_limits<unsigned>::max(); |
941 | } |
942 | |
943 | |
944 | |
945 | |
946 | |
947 | |
948 | |
949 | |
950 | |
951 | |
952 | |
953 | |
954 | |
955 | |
956 | |
957 | |
958 | |
959 | |
960 | |
961 | |
962 | |
963 | |
964 | |
965 | |
966 | |
967 | |
968 | void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "", |
969 | StringRef Arg2 = "", StringRef Arg3 = ""); |
970 | |
971 | |
972 | void Clear() { CurDiagID = std::numeric_limits<unsigned>::max(); } |
973 | |
974 | |
975 | StringRef getFlagValue() const { return FlagValue; } |
976 | |
977 | private: |
978 | |
979 | |
980 | |
981 | |
982 | |
983 | |
984 | friend class Diagnostic; |
985 | friend class DiagnosticBuilder; |
986 | friend class DiagnosticErrorTrap; |
987 | friend class DiagnosticIDs; |
988 | friend class PartialDiagnostic; |
989 | |
990 | |
991 | void ReportDelayed(); |
992 | |
993 | |
994 | SourceLocation CurDiagLoc; |
995 | |
996 | |
997 | |
998 | |
999 | |
1000 | unsigned CurDiagID; |
1001 | |
1002 | enum { |
1003 | |
1004 | |
1005 | |
1006 | |
1007 | |
1008 | MaxArguments = DiagnosticStorage::MaxArguments, |
1009 | }; |
1010 | |
1011 | DiagnosticStorage DiagStorage; |
1012 | |
1013 | DiagnosticMapping makeUserMapping(diag::Severity Map, SourceLocation L) { |
1014 | bool isPragma = L.isValid(); |
1015 | DiagnosticMapping Mapping = |
1016 | DiagnosticMapping::Make(Map, true, isPragma); |
1017 | |
1018 | |
1019 | |
1020 | if (isPragma) { |
1021 | Mapping.setNoWarningAsError(true); |
1022 | Mapping.setNoErrorAsFatal(true); |
1023 | } |
1024 | |
1025 | return Mapping; |
1026 | } |
1027 | |
1028 | |
1029 | |
1030 | |
1031 | bool ProcessDiag() { |
1032 | return Diags->ProcessDiag(*this); |
1033 | } |
1034 | |
1035 | |
1036 | |
1037 | protected: |
1038 | friend class ASTReader; |
1039 | friend class ASTWriter; |
1040 | |
1041 | |
1042 | |
1043 | |
1044 | |
1045 | friend class Sema; |
1046 | |
1047 | |
1048 | |
1049 | |
1050 | bool EmitCurrentDiagnostic(bool Force = false); |
1051 | |
1052 | unsigned getCurrentDiagID() const { return CurDiagID; } |
1053 | |
1054 | SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; } |
1055 | |
1056 | |
1057 | }; |
1058 | |
1059 | |
1060 | |
1061 | |
1062 | |
1063 | |
1064 | |
1065 | |
1066 | |
1067 | class DiagnosticErrorTrap { |
1068 | DiagnosticsEngine &Diag; |
1069 | unsigned NumErrors; |
1070 | unsigned NumUnrecoverableErrors; |
1071 | |
1072 | public: |
1073 | explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag) |
1074 | : Diag(Diag) { reset(); } |
1075 | |
1076 | |
1077 | |
1078 | bool hasErrorOccurred() const { |
1079 | return Diag.TrapNumErrorsOccurred > NumErrors; |
1080 | } |
1081 | |
1082 | |
1083 | |
1084 | bool hasUnrecoverableErrorOccurred() const { |
1085 | return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors; |
1086 | } |
1087 | |
1088 | |
1089 | void reset() { |
1090 | NumErrors = Diag.TrapNumErrorsOccurred; |
1091 | NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred; |
1092 | } |
1093 | }; |
1094 | |
1095 | |
1096 | |
1097 | |
1098 | |
1099 | |
1100 | |
1101 | |
1102 | |
1103 | |
1104 | |
1105 | class StreamingDiagnostic { |
1106 | public: |
1107 | |
1108 | |
1109 | class DiagStorageAllocator { |
1110 | static const unsigned NumCached = 16; |
1111 | DiagnosticStorage Cached[NumCached]; |
1112 | DiagnosticStorage *FreeList[NumCached]; |
1113 | unsigned NumFreeListEntries; |
1114 | |
1115 | public: |
1116 | DiagStorageAllocator(); |
1117 | ~DiagStorageAllocator(); |
1118 | |
1119 | |
1120 | DiagnosticStorage *Allocate() { |
1121 | if (NumFreeListEntries == 0) |
1122 | return new DiagnosticStorage; |
1123 | |
1124 | DiagnosticStorage *Result = FreeList[--NumFreeListEntries]; |
1125 | Result->NumDiagArgs = 0; |
1126 | Result->DiagRanges.clear(); |
1127 | Result->FixItHints.clear(); |
1128 | return Result; |
1129 | } |
1130 | |
1131 | |
1132 | void Deallocate(DiagnosticStorage *S) { |
1133 | if (S >= Cached && S <= Cached + NumCached) { |
1134 | FreeList[NumFreeListEntries++] = S; |
1135 | return; |
1136 | } |
1137 | |
1138 | delete S; |
1139 | } |
1140 | }; |
1141 | |
1142 | protected: |
1143 | mutable DiagnosticStorage *DiagStorage = nullptr; |
1144 | |
1145 | |
1146 | DiagStorageAllocator *Allocator = nullptr; |
| 23 | | Null pointer value stored to field 'Allocator' | |
|
1147 | |
1148 | public: |
1149 | |
1150 | DiagnosticStorage *getStorage() const { |
1151 | if (DiagStorage) |
| |
1152 | return DiagStorage; |
1153 | |
1154 | assert(Allocator); |
1155 | DiagStorage = Allocator->Allocate(); |
| 44 | | Called C++ object pointer is null |
|
1156 | return DiagStorage; |
1157 | } |
1158 | |
1159 | void freeStorage() { |
1160 | if (!DiagStorage) |
| 31 | | Assuming pointer value is null | |
|
| 32 | | Assuming field 'DiagStorage' is null | |
|
| |
1161 | return; |
1162 | |
1163 | |
1164 | |
1165 | |
1166 | |
1167 | |
1168 | |
1169 | freeStorageSlow(); |
1170 | } |
1171 | |
1172 | void freeStorageSlow() { |
1173 | if (!Allocator) |
1174 | return; |
1175 | Allocator->Deallocate(DiagStorage); |
1176 | DiagStorage = nullptr; |
1177 | } |
1178 | |
1179 | void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const { |
1180 | if (!DiagStorage) |
| |
1181 | DiagStorage = getStorage(); |
| 42 | | Calling 'StreamingDiagnostic::getStorage' | |
|
1182 | |
1183 | assert(DiagStorage->NumDiagArgs < DiagnosticStorage::MaxArguments && |
1184 | "Too many arguments to diagnostic!"); |
1185 | DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind; |
1186 | DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V; |
1187 | } |
1188 | |
1189 | void AddString(StringRef V) const { |
1190 | if (!DiagStorage) |
1191 | DiagStorage = getStorage(); |
1192 | |
1193 | assert(DiagStorage->NumDiagArgs < DiagnosticStorage::MaxArguments && |
1194 | "Too many arguments to diagnostic!"); |
1195 | DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = |
1196 | DiagnosticsEngine::ak_std_string; |
1197 | DiagStorage->DiagArgumentsStr[DiagStorage->NumDiagArgs++] = std::string(V); |
1198 | } |
1199 | |
1200 | void AddSourceRange(const CharSourceRange &R) const { |
1201 | if (!DiagStorage) |
1202 | DiagStorage = getStorage(); |
1203 | |
1204 | DiagStorage->DiagRanges.push_back(R); |
1205 | } |
1206 | |
1207 | void AddFixItHint(const FixItHint &Hint) const { |
1208 | if (Hint.isNull()) |
1209 | return; |
1210 | |
1211 | if (!DiagStorage) |
1212 | DiagStorage = getStorage(); |
1213 | |
1214 | DiagStorage->FixItHints.push_back(Hint); |
1215 | } |
1216 | |
1217 | |
1218 | |
1219 | |
1220 | |
1221 | |
1222 | |
1223 | |
1224 | operator bool() const { return true; } |
1225 | |
1226 | protected: |
1227 | StreamingDiagnostic() = default; |
| 24 | | Returning without writing to 'this->Allocator' | |
|
1228 | |
1229 | |
1230 | |
1231 | explicit StreamingDiagnostic(DiagnosticStorage *Storage) |
1232 | : DiagStorage(Storage) {} |
1233 | |
1234 | |
1235 | |
1236 | explicit StreamingDiagnostic(DiagStorageAllocator &Alloc) |
1237 | : Allocator(&Alloc) {} |
1238 | |
1239 | StreamingDiagnostic(const StreamingDiagnostic &Diag) = default; |
1240 | StreamingDiagnostic(StreamingDiagnostic &&Diag) = default; |
1241 | |
1242 | ~StreamingDiagnostic() { freeStorage(); } |
| 30 | | Calling 'StreamingDiagnostic::freeStorage' | |
|
| 34 | | Returning from 'StreamingDiagnostic::freeStorage' | |
|
1243 | }; |
1244 | |
1245 | |
1246 | |
1247 | |
1248 | |
1249 | |
1250 | |
1251 | |
1252 | |
1253 | |
1254 | |
1255 | |
1256 | |
1257 | |
1258 | |
1259 | |
1260 | |
1261 | class DiagnosticBuilder : public StreamingDiagnostic { |
1262 | friend class DiagnosticsEngine; |
1263 | friend class PartialDiagnostic; |
1264 | |
1265 | mutable DiagnosticsEngine *DiagObj = nullptr; |
1266 | |
1267 | |
1268 | |
1269 | |
1270 | |
1271 | |
1272 | mutable bool IsActive = false; |
1273 | |
1274 | |
1275 | |
1276 | mutable bool IsForceEmit = false; |
1277 | |
1278 | DiagnosticBuilder() = default; |
1279 | |
1280 | explicit DiagnosticBuilder(DiagnosticsEngine *diagObj) |
1281 | : StreamingDiagnostic(&diagObj->DiagStorage), DiagObj(diagObj), |
1282 | IsActive(true) { |
1283 | assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!"); |
1284 | assert(DiagStorage && |
1285 | "DiagnosticBuilder requires a valid DiagnosticStorage!"); |
1286 | DiagStorage->NumDiagArgs = 0; |
1287 | DiagStorage->DiagRanges.clear(); |
1288 | DiagStorage->FixItHints.clear(); |
1289 | } |
1290 | |
1291 | protected: |
1292 | |
1293 | void Clear() const { |
1294 | DiagObj = nullptr; |
1295 | IsActive = false; |
1296 | IsForceEmit = false; |
1297 | } |
1298 | |
1299 | |
1300 | bool isActive() const { return IsActive; } |
1301 | |
1302 | |
1303 | |
1304 | |
1305 | |
1306 | |
1307 | |
1308 | |
1309 | bool Emit() { |
1310 | |
1311 | |
1312 | if (!isActive()) return false; |
1313 | |
1314 | |
1315 | bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit); |
1316 | |
1317 | |
1318 | Clear(); |
1319 | |
1320 | return Result; |
1321 | } |
1322 | |
1323 | public: |
1324 | |
1325 | |
1326 | DiagnosticBuilder(const DiagnosticBuilder &D) : StreamingDiagnostic() { |
| 22 | | Calling defaulted default constructor for 'StreamingDiagnostic' | |
|
| 25 | | Returning from default constructor for 'StreamingDiagnostic' | |
|
1327 | DiagObj = D.DiagObj; |
1328 | DiagStorage = D.DiagStorage; |
1329 | IsActive = D.IsActive; |
1330 | IsForceEmit = D.IsForceEmit; |
1331 | D.Clear(); |
1332 | } |
| 26 | | Returning without writing to 'this->Allocator' | |
|
1333 | |
1334 | template <typename T> const DiagnosticBuilder &operator<<(const T &V) const { |
1335 | assert(isActive() && "Clients must not add to cleared diagnostic!"); |
1336 | const StreamingDiagnostic &DB = *this; |
1337 | DB << V; |
1338 | return *this; |
1339 | } |
1340 | |
1341 | |
1342 | |
1343 | |
1344 | template <typename T, typename = typename std::enable_if< |
1345 | !std::is_lvalue_reference<T>::value>::type> |
1346 | const DiagnosticBuilder &operator<<(T &&V) const { |
1347 | assert(isActive() && "Clients must not add to cleared diagnostic!"); |
1348 | const StreamingDiagnostic &DB = *this; |
1349 | DB << std::move(V); |
| |
1350 | return *this; |
1351 | } |
1352 | |
1353 | DiagnosticBuilder &operator=(const DiagnosticBuilder &) = delete; |
1354 | |
1355 | |
1356 | ~DiagnosticBuilder() { Emit(); } |
| 29 | | Calling '~StreamingDiagnostic' | |
|
| 35 | | Returning from '~StreamingDiagnostic' | |
|
1357 | |
1358 | |
1359 | const DiagnosticBuilder &setForceEmit() const { |
1360 | IsForceEmit = true; |
1361 | return *this; |
1362 | } |
1363 | |
1364 | void addFlagValue(StringRef V) const { DiagObj->FlagValue = std::string(V); } |
1365 | }; |
1366 | |
1367 | struct AddFlagValue { |
1368 | StringRef Val; |
1369 | |
1370 | explicit AddFlagValue(StringRef V) : Val(V) {} |
1371 | }; |
1372 | |
1373 | |
1374 | |
1375 | |
1376 | |
1377 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1378 | const AddFlagValue V) { |
1379 | DB.addFlagValue(V.Val); |
1380 | return DB; |
1381 | } |
1382 | |
1383 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1384 | StringRef S) { |
1385 | DB.AddString(S); |
1386 | return DB; |
1387 | } |
1388 | |
1389 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1390 | const char *Str) { |
1391 | DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str), |
1392 | DiagnosticsEngine::ak_c_string); |
1393 | return DB; |
1394 | } |
1395 | |
1396 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1397 | int I) { |
1398 | DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint); |
1399 | return DB; |
1400 | } |
1401 | |
1402 | |
1403 | |
1404 | template <typename T> |
1405 | inline std::enable_if_t<std::is_same<T, bool>::value, |
1406 | const StreamingDiagnostic &> |
1407 | operator<<(const StreamingDiagnostic &DB, T I) { |
1408 | DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint); |
1409 | return DB; |
1410 | } |
1411 | |
1412 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1413 | unsigned I) { |
1414 | DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint); |
1415 | return DB; |
1416 | } |
1417 | |
1418 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1419 | tok::TokenKind I) { |
1420 | DB.AddTaggedVal(static_cast<unsigned>(I), DiagnosticsEngine::ak_tokenkind); |
| 40 | | Calling 'StreamingDiagnostic::AddTaggedVal' | |
|
1421 | return DB; |
1422 | } |
1423 | |
1424 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1425 | const IdentifierInfo *II) { |
1426 | DB.AddTaggedVal(reinterpret_cast<intptr_t>(II), |
1427 | DiagnosticsEngine::ak_identifierinfo); |
1428 | return DB; |
1429 | } |
1430 | |
1431 | |
1432 | |
1433 | |
1434 | |
1435 | template <typename T> |
1436 | inline std::enable_if_t< |
1437 | std::is_same<std::remove_const_t<T>, DeclContext>::value, |
1438 | const StreamingDiagnostic &> |
1439 | operator<<(const StreamingDiagnostic &DB, T *DC) { |
1440 | DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC), |
1441 | DiagnosticsEngine::ak_declcontext); |
1442 | return DB; |
1443 | } |
1444 | |
1445 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1446 | SourceRange R) { |
1447 | DB.AddSourceRange(CharSourceRange::getTokenRange(R)); |
1448 | return DB; |
1449 | } |
1450 | |
1451 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1452 | ArrayRef<SourceRange> Ranges) { |
1453 | for (SourceRange R : Ranges) |
1454 | DB.AddSourceRange(CharSourceRange::getTokenRange(R)); |
1455 | return DB; |
1456 | } |
1457 | |
1458 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1459 | const CharSourceRange &R) { |
1460 | DB.AddSourceRange(R); |
1461 | return DB; |
1462 | } |
1463 | |
1464 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1465 | const FixItHint &Hint) { |
1466 | DB.AddFixItHint(Hint); |
1467 | return DB; |
1468 | } |
1469 | |
1470 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1471 | ArrayRef<FixItHint> Hints) { |
1472 | for (const FixItHint &Hint : Hints) |
1473 | DB.AddFixItHint(Hint); |
1474 | return DB; |
1475 | } |
1476 | |
1477 | inline const StreamingDiagnostic & |
1478 | operator<<(const StreamingDiagnostic &DB, |
1479 | const llvm::Optional<SourceRange> &Opt) { |
1480 | if (Opt) |
1481 | DB << *Opt; |
1482 | return DB; |
1483 | } |
1484 | |
1485 | inline const StreamingDiagnostic & |
1486 | operator<<(const StreamingDiagnostic &DB, |
1487 | const llvm::Optional<CharSourceRange> &Opt) { |
1488 | if (Opt) |
1489 | DB << *Opt; |
1490 | return DB; |
1491 | } |
1492 | |
1493 | inline const StreamingDiagnostic & |
1494 | operator<<(const StreamingDiagnostic &DB, |
1495 | const llvm::Optional<FixItHint> &Opt) { |
1496 | if (Opt) |
1497 | DB << *Opt; |
1498 | return DB; |
1499 | } |
1500 | |
1501 | |
1502 | |
1503 | using DiagNullabilityKind = std::pair<NullabilityKind, bool>; |
1504 | |
1505 | const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1506 | DiagNullabilityKind nullability); |
1507 | |
1508 | inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc, |
1509 | unsigned DiagID) { |
1510 | assert(CurDiagID == std::numeric_limits<unsigned>::max() && |
1511 | "Multiple diagnostics in flight at once!"); |
1512 | CurDiagLoc = Loc; |
1513 | CurDiagID = DiagID; |
1514 | FlagValue.clear(); |
1515 | return DiagnosticBuilder(this); |
1516 | } |
1517 | |
1518 | const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1519 | llvm::Error &&E); |
1520 | |
1521 | inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) { |
1522 | return Report(SourceLocation(), DiagID); |
1523 | } |
1524 | |
1525 | |
1526 | |
1527 | |
1528 | |
1529 | |
1530 | |
1531 | |
1532 | class Diagnostic { |
1533 | const DiagnosticsEngine *DiagObj; |
1534 | StringRef StoredDiagMessage; |
1535 | |
1536 | public: |
1537 | explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {} |
1538 | Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage) |
1539 | : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {} |
1540 | |
1541 | const DiagnosticsEngine *getDiags() const { return DiagObj; } |
1542 | unsigned getID() const { return DiagObj->CurDiagID; } |
1543 | const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; } |
1544 | bool hasSourceManager() const { return DiagObj->hasSourceManager(); } |
1545 | SourceManager &getSourceManager() const { return DiagObj->getSourceManager();} |
1546 | |
1547 | unsigned getNumArgs() const { return DiagObj->DiagStorage.NumDiagArgs; } |
1548 | |
1549 | |
1550 | |
1551 | |
1552 | |
1553 | |
1554 | |
1555 | DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const { |
1556 | assert(Idx < getNumArgs() && "Argument index out of range!"); |
1557 | return (DiagnosticsEngine::ArgumentKind) |
1558 | DiagObj->DiagStorage.DiagArgumentsKind[Idx]; |
1559 | } |
1560 | |
1561 | |
1562 | |
1563 | const std::string &getArgStdStr(unsigned Idx) const { |
1564 | assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string && |
1565 | "invalid argument accessor!"); |
1566 | return DiagObj->DiagStorage.DiagArgumentsStr[Idx]; |
1567 | } |
1568 | |
1569 | |
1570 | |
1571 | const char *getArgCStr(unsigned Idx) const { |
1572 | assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string && |
1573 | "invalid argument accessor!"); |
1574 | return reinterpret_cast<const char *>( |
1575 | DiagObj->DiagStorage.DiagArgumentsVal[Idx]); |
1576 | } |
1577 | |
1578 | |
1579 | |
1580 | int getArgSInt(unsigned Idx) const { |
1581 | assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint && |
1582 | "invalid argument accessor!"); |
1583 | return (int)DiagObj->DiagStorage.DiagArgumentsVal[Idx]; |
1584 | } |
1585 | |
1586 | |
1587 | |
1588 | unsigned getArgUInt(unsigned Idx) const { |
1589 | assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint && |
1590 | "invalid argument accessor!"); |
1591 | return (unsigned)DiagObj->DiagStorage.DiagArgumentsVal[Idx]; |
1592 | } |
1593 | |
1594 | |
1595 | |
1596 | const IdentifierInfo *getArgIdentifier(unsigned Idx) const { |
1597 | assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo && |
1598 | "invalid argument accessor!"); |
1599 | return reinterpret_cast<IdentifierInfo *>( |
1600 | DiagObj->DiagStorage.DiagArgumentsVal[Idx]); |
1601 | } |
1602 | |
1603 | |
1604 | |
1605 | intptr_t getRawArg(unsigned Idx) const { |
1606 | assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string && |
1607 | "invalid argument accessor!"); |
1608 | return DiagObj->DiagStorage.DiagArgumentsVal[Idx]; |
1609 | } |
1610 | |
1611 | |
1612 | unsigned getNumRanges() const { |
1613 | return DiagObj->DiagStorage.DiagRanges.size(); |
1614 | } |
1615 | |
1616 | |
1617 | const CharSourceRange &getRange(unsigned Idx) const { |
1618 | assert(Idx < getNumRanges() && "Invalid diagnostic range index!"); |
1619 | return DiagObj->DiagStorage.DiagRanges[Idx]; |
1620 | } |
1621 | |
1622 | |
1623 | ArrayRef<CharSourceRange> getRanges() const { |
1624 | return DiagObj->DiagStorage.DiagRanges; |
1625 | } |
1626 | |
1627 | unsigned getNumFixItHints() const { |
1628 | return DiagObj->DiagStorage.FixItHints.size(); |
1629 | } |
1630 | |
1631 | const FixItHint &getFixItHint(unsigned Idx) const { |
1632 | assert(Idx < getNumFixItHints() && "Invalid index!"); |
1633 | return DiagObj->DiagStorage.FixItHints[Idx]; |
1634 | } |
1635 | |
1636 | ArrayRef<FixItHint> getFixItHints() const { |
1637 | return DiagObj->DiagStorage.FixItHints; |
1638 | } |
1639 | |
1640 | |
1641 | |
1642 | |
1643 | |
1644 | void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const; |
1645 | |
1646 | |
1647 | |
1648 | void FormatDiagnostic(const char *DiagStr, const char *DiagEnd, |
1649 | SmallVectorImpl<char> &OutStr) const; |
1650 | }; |
1651 | |
1652 | |
1653 | |
1654 | |
1655 | |
1656 | class StoredDiagnostic { |
1657 | unsigned ID; |
1658 | DiagnosticsEngine::Level Level; |
1659 | FullSourceLoc Loc; |
1660 | std::string Message; |
1661 | std::vector<CharSourceRange> Ranges; |
1662 | std::vector<FixItHint> FixIts; |
1663 | |
1664 | public: |
1665 | StoredDiagnostic() = default; |
1666 | StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info); |
1667 | StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID, |
1668 | StringRef Message); |
1669 | StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID, |
1670 | StringRef Message, FullSourceLoc Loc, |
1671 | ArrayRef<CharSourceRange> Ranges, |
1672 | ArrayRef<FixItHint> Fixits); |
1673 | |
1674 | |
1675 | explicit operator bool() const { return !Message.empty(); } |
1676 | |
1677 | unsigned getID() const { return ID; } |
1678 | DiagnosticsEngine::Level getLevel() const { return Level; } |
1679 | const FullSourceLoc &getLocation() const { return Loc; } |
1680 | StringRef getMessage() const { return Message; } |
1681 | |
1682 | void setLocation(FullSourceLoc Loc) { this->Loc = Loc; } |
1683 | |
1684 | using range_iterator = std::vector<CharSourceRange>::const_iterator; |
1685 | |
1686 | range_iterator range_begin() const { return Ranges.begin(); } |
1687 | range_iterator range_end() const { return Ranges.end(); } |
1688 | unsigned range_size() const { return Ranges.size(); } |
1689 | |
1690 | ArrayRef<CharSourceRange> getRanges() const { |
1691 | return llvm::makeArrayRef(Ranges); |
1692 | } |
1693 | |
1694 | using fixit_iterator = std::vector<FixItHint>::const_iterator; |
1695 | |
1696 | fixit_iterator fixit_begin() const { return FixIts.begin(); } |
1697 | fixit_iterator fixit_end() const { return FixIts.end(); } |
1698 | unsigned fixit_size() const { return FixIts.size(); } |
1699 | |
1700 | ArrayRef<FixItHint> getFixIts() const { |
1701 | return llvm::makeArrayRef(FixIts); |
1702 | } |
1703 | }; |
1704 | |
1705 | |
1706 | |
1707 | class DiagnosticConsumer { |
1708 | protected: |
1709 | unsigned NumWarnings = 0; |
1710 | unsigned NumErrors = 0; |
1711 | |
1712 | public: |
1713 | DiagnosticConsumer() = default; |
1714 | virtual ~DiagnosticConsumer(); |
1715 | |
1716 | unsigned getNumErrors() const { return NumErrors; } |
1717 | unsigned getNumWarnings() const { return NumWarnings; } |
1718 | virtual void clear() { NumWarnings = NumErrors = 0; } |
1719 | |
1720 | |
1721 | |
1722 | |
1723 | |
1724 | |
1725 | |
1726 | |
1727 | |
1728 | |
1729 | |
1730 | |
1731 | virtual void BeginSourceFile(const LangOptions &LangOpts, |
1732 | const Preprocessor *PP = nullptr) {} |
1733 | |
1734 | |
1735 | |
1736 | |
1737 | |
1738 | |
1739 | virtual void EndSourceFile() {} |
1740 | |
1741 | |
1742 | |
1743 | virtual void finish() {} |
1744 | |
1745 | |
1746 | |
1747 | |
1748 | |
1749 | |
1750 | virtual bool IncludeInDiagnosticCounts() const; |
1751 | |
1752 | |
1753 | |
1754 | |
1755 | |
1756 | |
1757 | virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, |
1758 | const Diagnostic &Info); |
1759 | }; |
1760 | |
1761 | |
1762 | class IgnoringDiagConsumer : public DiagnosticConsumer { |
1763 | virtual void anchor(); |
1764 | |
1765 | void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, |
1766 | const Diagnostic &Info) override { |
1767 | |
1768 | } |
1769 | }; |
1770 | |
1771 | |
1772 | |
1773 | |
1774 | class ForwardingDiagnosticConsumer : public DiagnosticConsumer { |
1775 | DiagnosticConsumer &Target; |
1776 | |
1777 | public: |
1778 | ForwardingDiagnosticConsumer(DiagnosticConsumer &Target) : Target(Target) {} |
1779 | ~ForwardingDiagnosticConsumer() override; |
1780 | |
1781 | void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, |
1782 | const Diagnostic &Info) override; |
1783 | void clear() override; |
1784 | |
1785 | bool IncludeInDiagnosticCounts() const override; |
1786 | }; |
1787 | |
1788 | |
1789 | struct TemplateDiffTypes { |
1790 | intptr_t FromType; |
1791 | intptr_t ToType; |
1792 | unsigned PrintTree : 1; |
1793 | unsigned PrintFromType : 1; |
1794 | unsigned ElideType : 1; |
1795 | unsigned ShowColors : 1; |
1796 | |
1797 | |
1798 | unsigned TemplateDiffUsed : 1; |
1799 | }; |
1800 | |
1801 | |
1802 | |
1803 | const char ToggleHighlight = 127; |
1804 | |
1805 | |
1806 | |
1807 | void ProcessWarningOptions(DiagnosticsEngine &Diags, |
1808 | const DiagnosticOptions &Opts, |
1809 | bool ReportDiags = true); |
1810 | |
1811 | } |
1812 | |
1813 | #endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H |