clang 22.0.0git
ParsePragma.cpp
Go to the documentation of this file.
1//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the language specific #pragma handlers.
10//
11//===----------------------------------------------------------------------===//
12
18#include "clang/Lex/Token.h"
20#include "clang/Parse/Parser.h"
23#include "clang/Sema/Scope.h"
24#include "clang/Sema/SemaCUDA.h"
27#include "llvm/ADT/ArrayRef.h"
28#include "llvm/ADT/StringSwitch.h"
29#include <optional>
30using namespace clang;
31
32namespace {
33
34struct PragmaAlignHandler : public PragmaHandler {
35 explicit PragmaAlignHandler() : PragmaHandler("align") {}
36 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
37 Token &FirstToken) override;
38};
39
40struct PragmaGCCVisibilityHandler : public PragmaHandler {
41 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
42 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
43 Token &FirstToken) override;
44};
45
46struct PragmaOptionsHandler : public PragmaHandler {
47 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
48 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
49 Token &FirstToken) override;
50};
51
52struct PragmaPackHandler : public PragmaHandler {
53 explicit PragmaPackHandler() : PragmaHandler("pack") {}
54 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
55 Token &FirstToken) override;
56};
57
58struct PragmaClangSectionHandler : public PragmaHandler {
59 explicit PragmaClangSectionHandler(Sema &S)
60 : PragmaHandler("section"), Actions(S) {}
61 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
62 Token &FirstToken) override;
63
64private:
65 Sema &Actions;
66};
67
68struct PragmaMSStructHandler : public PragmaHandler {
69 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
70 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
71 Token &FirstToken) override;
72};
73
74struct PragmaUnusedHandler : public PragmaHandler {
75 PragmaUnusedHandler() : PragmaHandler("unused") {}
76 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
77 Token &FirstToken) override;
78};
79
80struct PragmaWeakHandler : public PragmaHandler {
81 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
82 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
83 Token &FirstToken) override;
84};
85
86struct PragmaRedefineExtnameHandler : public PragmaHandler {
87 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
88 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
89 Token &FirstToken) override;
90};
91
92struct PragmaOpenCLExtensionHandler : public PragmaHandler {
93 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
94 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
95 Token &FirstToken) override;
96};
97
98
99struct PragmaFPContractHandler : public PragmaHandler {
100 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
101 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
102 Token &FirstToken) override;
103};
104
105// Pragma STDC implementations.
106
107/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
108struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
109 PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
110
111 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
112 Token &Tok) override {
113 Token PragmaName = Tok;
114 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
115 PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
116 << PragmaName.getIdentifierInfo()->getName();
117 return;
118 }
120 if (PP.LexOnOffSwitch(OOS))
121 return;
122
123 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
124 1);
125 Toks[0].startToken();
126 Toks[0].setKind(tok::annot_pragma_fenv_access);
127 Toks[0].setLocation(Tok.getLocation());
128 Toks[0].setAnnotationEndLoc(Tok.getLocation());
129 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
130 static_cast<uintptr_t>(OOS)));
131 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
132 /*IsReinject=*/false);
133 }
134};
135
136/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
137struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
138 PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
139
140 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
141 Token &Tok) override {
143 if (PP.LexOnOffSwitch(OOS))
144 return;
145
146 MutableArrayRef<Token> Toks(
147 PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
148
149 Toks[0].startToken();
150 Toks[0].setKind(tok::annot_pragma_cx_limited_range);
151 Toks[0].setLocation(Tok.getLocation());
152 Toks[0].setAnnotationEndLoc(Tok.getLocation());
153 Toks[0].setAnnotationValue(
154 reinterpret_cast<void *>(static_cast<uintptr_t>(OOS)));
155 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
156 /*IsReinject=*/false);
157 }
158};
159
160/// Handler for "\#pragma STDC FENV_ROUND ...".
161struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler {
162 PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}
163
164 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
165 Token &Tok) override;
166};
167
168/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
169struct PragmaSTDC_UnknownHandler : public PragmaHandler {
170 PragmaSTDC_UnknownHandler() = default;
171
172 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
173 Token &UnknownTok) override {
174 // C99 6.10.6p2, unknown forms are not allowed.
175 PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
176 }
177};
178
179struct PragmaFPHandler : public PragmaHandler {
180 PragmaFPHandler() : PragmaHandler("fp") {}
181 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
182 Token &FirstToken) override;
183};
184
185// A pragma handler to be the base of the NoOpenMPHandler and NoOpenACCHandler,
186// which are identical other than the name given to them, and the diagnostic
187// emitted.
188template <diag::kind IgnoredDiag>
189struct PragmaNoSupportHandler : public PragmaHandler {
190 PragmaNoSupportHandler(StringRef Name) : PragmaHandler(Name) {}
191 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
192 Token &FirstToken) override;
193};
194
195struct PragmaNoOpenMPHandler
196 : public PragmaNoSupportHandler<diag::warn_pragma_omp_ignored> {
197 PragmaNoOpenMPHandler() : PragmaNoSupportHandler("omp") {}
198};
199
200struct PragmaNoOpenACCHandler
201 : public PragmaNoSupportHandler<diag::warn_pragma_acc_ignored> {
202 PragmaNoOpenACCHandler() : PragmaNoSupportHandler("acc") {}
203};
204
205// A pragma handler to be the base for the OpenMPHandler and OpenACCHandler,
206// which are identical other than the tokens used for the start/end of a pragma
207// section, and some diagnostics.
208template <tok::TokenKind StartTok, tok::TokenKind EndTok,
209 diag::kind UnexpectedDiag>
210struct PragmaSupportHandler : public PragmaHandler {
211 PragmaSupportHandler(StringRef Name) : PragmaHandler(Name) {}
212 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
213 Token &FirstToken) override;
214};
215
216struct PragmaOpenMPHandler
217 : public PragmaSupportHandler<tok::annot_pragma_openmp,
218 tok::annot_pragma_openmp_end,
219 diag::err_omp_unexpected_directive> {
220 PragmaOpenMPHandler() : PragmaSupportHandler("omp") {}
221};
222
223struct PragmaOpenACCHandler
224 : public PragmaSupportHandler<tok::annot_pragma_openacc,
225 tok::annot_pragma_openacc_end,
226 diag::err_acc_unexpected_directive> {
227 PragmaOpenACCHandler() : PragmaSupportHandler("acc") {}
228};
229
230/// PragmaCommentHandler - "\#pragma comment ...".
231struct PragmaCommentHandler : public PragmaHandler {
232 PragmaCommentHandler(Sema &Actions)
233 : PragmaHandler("comment"), Actions(Actions) {}
234 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
235 Token &FirstToken) override;
236
237private:
238 Sema &Actions;
239};
240
241struct PragmaDetectMismatchHandler : public PragmaHandler {
242 PragmaDetectMismatchHandler(Sema &Actions)
243 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
244 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
245 Token &FirstToken) override;
246
247private:
248 Sema &Actions;
249};
250
251struct PragmaFloatControlHandler : public PragmaHandler {
252 PragmaFloatControlHandler(Sema &Actions)
253 : PragmaHandler("float_control") {}
254 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
255 Token &FirstToken) override;
256};
257
258struct PragmaMSPointersToMembers : public PragmaHandler {
259 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
260 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
261 Token &FirstToken) override;
262};
263
264struct PragmaMSVtorDisp : public PragmaHandler {
265 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
266 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
267 Token &FirstToken) override;
268};
269
270struct PragmaMSPragma : public PragmaHandler {
271 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
272 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
273 Token &FirstToken) override;
274};
275
276/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
277struct PragmaOptimizeHandler : public PragmaHandler {
278 PragmaOptimizeHandler(Sema &S)
279 : PragmaHandler("optimize"), Actions(S) {}
280 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
281 Token &FirstToken) override;
282
283private:
284 Sema &Actions;
285};
286
287struct PragmaLoopHintHandler : public PragmaHandler {
288 PragmaLoopHintHandler() : PragmaHandler("loop") {}
289 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
290 Token &FirstToken) override;
291};
292
293struct PragmaUnrollHintHandler : public PragmaHandler {
294 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
295 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
296 Token &FirstToken) override;
297};
298
299struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
300 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
301};
302
303// "\#pragma fenv_access (on)".
304struct PragmaMSFenvAccessHandler : public PragmaHandler {
305 PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {}
306 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
307 Token &FirstToken) override {
308 StringRef PragmaName = FirstToken.getIdentifierInfo()->getName();
309 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
310 PP.Diag(FirstToken.getLocation(), diag::warn_pragma_fp_ignored)
311 << PragmaName;
312 return;
313 }
314
315 Token Tok;
316 PP.Lex(Tok);
317 if (Tok.isNot(tok::l_paren)) {
318 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
319 << PragmaName;
320 return;
321 }
322 PP.Lex(Tok); // Consume the l_paren.
323 if (Tok.isNot(tok::identifier)) {
324 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
325 return;
326 }
327 const IdentifierInfo *II = Tok.getIdentifierInfo();
329 if (II->isStr("on")) {
330 OOS = tok::OOS_ON;
331 PP.Lex(Tok);
332 } else if (II->isStr("off")) {
333 OOS = tok::OOS_OFF;
334 PP.Lex(Tok);
335 } else {
336 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
337 return;
338 }
339 if (Tok.isNot(tok::r_paren)) {
340 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
341 << PragmaName;
342 return;
343 }
344 PP.Lex(Tok); // Consume the r_paren.
345
346 if (Tok.isNot(tok::eod)) {
347 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
348 << PragmaName;
349 return;
350 }
351
352 MutableArrayRef<Token> Toks(
353 PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
354 Toks[0].startToken();
355 Toks[0].setKind(tok::annot_pragma_fenv_access_ms);
356 Toks[0].setLocation(FirstToken.getLocation());
357 Toks[0].setAnnotationEndLoc(Tok.getLocation());
358 Toks[0].setAnnotationValue(
359 reinterpret_cast<void*>(static_cast<uintptr_t>(OOS)));
360 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
361 /*IsReinject=*/false);
362 }
363};
364
365struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
366 PragmaForceCUDAHostDeviceHandler(Sema &Actions)
367 : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
368 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
369 Token &FirstToken) override;
370
371private:
372 Sema &Actions;
373};
374
375/// PragmaAttributeHandler - "\#pragma clang attribute ...".
376struct PragmaAttributeHandler : public PragmaHandler {
377 PragmaAttributeHandler(AttributeFactory &AttrFactory)
378 : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
379 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
380 Token &FirstToken) override;
381
382 /// A pool of attributes that were parsed in \#pragma clang attribute.
383 ParsedAttributes AttributesForPragmaAttribute;
384};
385
386struct PragmaMaxTokensHereHandler : public PragmaHandler {
387 PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
388 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
389 Token &FirstToken) override;
390};
391
392struct PragmaMaxTokensTotalHandler : public PragmaHandler {
393 PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
394 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
395 Token &FirstToken) override;
396};
397
398struct PragmaRISCVHandler : public PragmaHandler {
399 PragmaRISCVHandler(Sema &Actions)
400 : PragmaHandler("riscv"), Actions(Actions) {}
401 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
402 Token &FirstToken) override;
403
404private:
405 Sema &Actions;
406};
407
408void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) {
409 for (auto &T : Toks)
411}
412} // end namespace
413
414void Parser::initializePragmaHandlers() {
415 AlignHandler = std::make_unique<PragmaAlignHandler>();
416 PP.AddPragmaHandler(AlignHandler.get());
417
418 GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
419 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
420
421 OptionsHandler = std::make_unique<PragmaOptionsHandler>();
422 PP.AddPragmaHandler(OptionsHandler.get());
423
424 PackHandler = std::make_unique<PragmaPackHandler>();
425 PP.AddPragmaHandler(PackHandler.get());
426
427 MSStructHandler = std::make_unique<PragmaMSStructHandler>();
428 PP.AddPragmaHandler(MSStructHandler.get());
429
430 UnusedHandler = std::make_unique<PragmaUnusedHandler>();
431 PP.AddPragmaHandler(UnusedHandler.get());
432
433 WeakHandler = std::make_unique<PragmaWeakHandler>();
434 PP.AddPragmaHandler(WeakHandler.get());
435
436 RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
437 PP.AddPragmaHandler(RedefineExtnameHandler.get());
438
439 FPContractHandler = std::make_unique<PragmaFPContractHandler>();
440 PP.AddPragmaHandler("STDC", FPContractHandler.get());
441
442 STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
443 PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get());
444
445 STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>();
446 PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get());
447
448 STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
449 PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
450
451 STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
452 PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
453
454 PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
455 PP.AddPragmaHandler("clang", PCSectionHandler.get());
456
457 if (getLangOpts().OpenCL) {
458 OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
459 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
460
461 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
462 }
463 if (getLangOpts().OpenMP)
464 OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
465 else
466 OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
467 PP.AddPragmaHandler(OpenMPHandler.get());
468
469 if (getLangOpts().OpenACC)
470 OpenACCHandler = std::make_unique<PragmaOpenACCHandler>();
471 else
472 OpenACCHandler = std::make_unique<PragmaNoOpenACCHandler>();
473 PP.AddPragmaHandler(OpenACCHandler.get());
474
475 if (getLangOpts().MicrosoftExt ||
476 getTargetInfo().getTriple().isOSBinFormatELF()) {
477 MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
478 PP.AddPragmaHandler(MSCommentHandler.get());
479 }
480
481 FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
482 PP.AddPragmaHandler(FloatControlHandler.get());
483 if (getLangOpts().MicrosoftExt) {
484 MSDetectMismatchHandler =
485 std::make_unique<PragmaDetectMismatchHandler>(Actions);
486 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
487 MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
488 PP.AddPragmaHandler(MSPointersToMembers.get());
489 MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
490 PP.AddPragmaHandler(MSVtorDisp.get());
491 MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
492 PP.AddPragmaHandler(MSInitSeg.get());
493 MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
494 PP.AddPragmaHandler(MSDataSeg.get());
495 MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
496 PP.AddPragmaHandler(MSBSSSeg.get());
497 MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
498 PP.AddPragmaHandler(MSConstSeg.get());
499 MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
500 PP.AddPragmaHandler(MSCodeSeg.get());
501 MSSection = std::make_unique<PragmaMSPragma>("section");
502 PP.AddPragmaHandler(MSSection.get());
503 MSStrictGuardStackCheck =
504 std::make_unique<PragmaMSPragma>("strict_gs_check");
505 PP.AddPragmaHandler(MSStrictGuardStackCheck.get());
506 MSFunction = std::make_unique<PragmaMSPragma>("function");
507 PP.AddPragmaHandler(MSFunction.get());
508 MSAllocText = std::make_unique<PragmaMSPragma>("alloc_text");
509 PP.AddPragmaHandler(MSAllocText.get());
510 MSOptimize = std::make_unique<PragmaMSPragma>("optimize");
511 PP.AddPragmaHandler(MSOptimize.get());
512 MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
513 PP.AddPragmaHandler(MSRuntimeChecks.get());
514 MSIntrinsic = std::make_unique<PragmaMSPragma>("intrinsic");
515 PP.AddPragmaHandler(MSIntrinsic.get());
516 MSFenvAccess = std::make_unique<PragmaMSFenvAccessHandler>();
517 PP.AddPragmaHandler(MSFenvAccess.get());
518 }
519
520 if (getLangOpts().CUDA) {
521 CUDAForceHostDeviceHandler =
522 std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
523 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
524 }
525
526 OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
527 PP.AddPragmaHandler("clang", OptimizeHandler.get());
528
529 LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
530 PP.AddPragmaHandler("clang", LoopHintHandler.get());
531
532 UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
533 PP.AddPragmaHandler(UnrollHintHandler.get());
534 PP.AddPragmaHandler("GCC", UnrollHintHandler.get());
535
536 NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
537 PP.AddPragmaHandler(NoUnrollHintHandler.get());
538 PP.AddPragmaHandler("GCC", NoUnrollHintHandler.get());
539
540 UnrollAndJamHintHandler =
541 std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
542 PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
543
544 NoUnrollAndJamHintHandler =
545 std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
546 PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
547
548 FPHandler = std::make_unique<PragmaFPHandler>();
549 PP.AddPragmaHandler("clang", FPHandler.get());
550
551 AttributePragmaHandler =
552 std::make_unique<PragmaAttributeHandler>(AttrFactory);
553 PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
554
555 MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
556 PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
557
558 MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
559 PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
560
561 if (getTargetInfo().getTriple().isRISCV()) {
562 RISCVPragmaHandler = std::make_unique<PragmaRISCVHandler>(Actions);
563 PP.AddPragmaHandler("clang", RISCVPragmaHandler.get());
564 }
565}
566
567void Parser::resetPragmaHandlers() {
568 // Remove the pragma handlers we installed.
569 PP.RemovePragmaHandler(AlignHandler.get());
570 AlignHandler.reset();
571 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
572 GCCVisibilityHandler.reset();
573 PP.RemovePragmaHandler(OptionsHandler.get());
574 OptionsHandler.reset();
575 PP.RemovePragmaHandler(PackHandler.get());
576 PackHandler.reset();
577 PP.RemovePragmaHandler(MSStructHandler.get());
578 MSStructHandler.reset();
579 PP.RemovePragmaHandler(UnusedHandler.get());
580 UnusedHandler.reset();
581 PP.RemovePragmaHandler(WeakHandler.get());
582 WeakHandler.reset();
583 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
584 RedefineExtnameHandler.reset();
585
586 if (getLangOpts().OpenCL) {
587 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
588 OpenCLExtensionHandler.reset();
589 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
590 }
591 PP.RemovePragmaHandler(OpenMPHandler.get());
592 OpenMPHandler.reset();
593
594 PP.RemovePragmaHandler(OpenACCHandler.get());
595 OpenACCHandler.reset();
596
597 if (getLangOpts().MicrosoftExt ||
598 getTargetInfo().getTriple().isOSBinFormatELF()) {
599 PP.RemovePragmaHandler(MSCommentHandler.get());
600 MSCommentHandler.reset();
601 }
602
603 PP.RemovePragmaHandler("clang", PCSectionHandler.get());
604 PCSectionHandler.reset();
605
606 PP.RemovePragmaHandler(FloatControlHandler.get());
607 FloatControlHandler.reset();
608 if (getLangOpts().MicrosoftExt) {
609 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
610 MSDetectMismatchHandler.reset();
611 PP.RemovePragmaHandler(MSPointersToMembers.get());
612 MSPointersToMembers.reset();
613 PP.RemovePragmaHandler(MSVtorDisp.get());
614 MSVtorDisp.reset();
615 PP.RemovePragmaHandler(MSInitSeg.get());
616 MSInitSeg.reset();
617 PP.RemovePragmaHandler(MSDataSeg.get());
618 MSDataSeg.reset();
619 PP.RemovePragmaHandler(MSBSSSeg.get());
620 MSBSSSeg.reset();
621 PP.RemovePragmaHandler(MSConstSeg.get());
622 MSConstSeg.reset();
623 PP.RemovePragmaHandler(MSCodeSeg.get());
624 MSCodeSeg.reset();
625 PP.RemovePragmaHandler(MSSection.get());
626 MSSection.reset();
627 PP.RemovePragmaHandler(MSStrictGuardStackCheck.get());
628 MSStrictGuardStackCheck.reset();
629 PP.RemovePragmaHandler(MSFunction.get());
630 MSFunction.reset();
631 PP.RemovePragmaHandler(MSAllocText.get());
632 MSAllocText.reset();
633 PP.RemovePragmaHandler(MSRuntimeChecks.get());
634 MSRuntimeChecks.reset();
635 PP.RemovePragmaHandler(MSIntrinsic.get());
636 MSIntrinsic.reset();
637 PP.RemovePragmaHandler(MSOptimize.get());
638 MSOptimize.reset();
639 PP.RemovePragmaHandler(MSFenvAccess.get());
640 MSFenvAccess.reset();
641 }
642
643 if (getLangOpts().CUDA) {
644 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
645 CUDAForceHostDeviceHandler.reset();
646 }
647
648 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
649 FPContractHandler.reset();
650
651 PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get());
652 STDCFenvAccessHandler.reset();
653
654 PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get());
655 STDCFenvRoundHandler.reset();
656
657 PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
658 STDCCXLIMITHandler.reset();
659
660 PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
661 STDCUnknownHandler.reset();
662
663 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
664 OptimizeHandler.reset();
665
666 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
667 LoopHintHandler.reset();
668
669 PP.RemovePragmaHandler(UnrollHintHandler.get());
670 PP.RemovePragmaHandler("GCC", UnrollHintHandler.get());
671 UnrollHintHandler.reset();
672
673 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
674 PP.RemovePragmaHandler("GCC", NoUnrollHintHandler.get());
675 NoUnrollHintHandler.reset();
676
677 PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
678 UnrollAndJamHintHandler.reset();
679
680 PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
681 NoUnrollAndJamHintHandler.reset();
682
683 PP.RemovePragmaHandler("clang", FPHandler.get());
684 FPHandler.reset();
685
686 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
687 AttributePragmaHandler.reset();
688
689 PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
690 MaxTokensHerePragmaHandler.reset();
691
692 PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
693 MaxTokensTotalPragmaHandler.reset();
694
695 if (getTargetInfo().getTriple().isRISCV()) {
696 PP.RemovePragmaHandler("clang", RISCVPragmaHandler.get());
697 RISCVPragmaHandler.reset();
698 }
699}
700
701void Parser::HandlePragmaUnused() {
702 assert(Tok.is(tok::annot_pragma_unused));
703 SourceLocation UnusedLoc = ConsumeAnnotationToken();
704 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
705 ConsumeToken(); // The argument token.
706}
707
708void Parser::HandlePragmaVisibility() {
709 assert(Tok.is(tok::annot_pragma_vis));
710 const IdentifierInfo *VisType =
711 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
712 SourceLocation VisLoc = ConsumeAnnotationToken();
713 Actions.ActOnPragmaVisibility(VisType, VisLoc);
714}
715
716void Parser::HandlePragmaPack() {
717 assert(Tok.is(tok::annot_pragma_pack));
718 Sema::PragmaPackInfo *Info =
719 static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue());
720 SourceLocation PragmaLoc = Tok.getLocation();
721 ExprResult Alignment;
722 if (Info->Alignment.is(tok::numeric_constant)) {
723 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
724 if (Alignment.isInvalid()) {
725 ConsumeAnnotationToken();
726 return;
727 }
728 }
729 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
730 Alignment.get());
731 // Consume the token after processing the pragma to enable pragma-specific
732 // #include warnings.
733 ConsumeAnnotationToken();
734}
735
736void Parser::HandlePragmaMSStruct() {
737 assert(Tok.is(tok::annot_pragma_msstruct));
739 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
740 Actions.ActOnPragmaMSStruct(Kind);
741 ConsumeAnnotationToken();
742}
743
744void Parser::HandlePragmaAlign() {
745 assert(Tok.is(tok::annot_pragma_align));
747 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
748 Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
749 // Consume the token after processing the pragma to enable pragma-specific
750 // #include warnings.
751 ConsumeAnnotationToken();
752}
753
754void Parser::HandlePragmaDump() {
755 assert(Tok.is(tok::annot_pragma_dump));
756 ConsumeAnnotationToken();
757 if (Tok.is(tok::eod)) {
758 PP.Diag(Tok, diag::warn_pragma_debug_missing_argument) << "dump";
759 } else if (NextToken().is(tok::eod)) {
760 if (Tok.isNot(tok::identifier)) {
761 PP.Diag(Tok, diag::warn_pragma_debug_unexpected_argument);
763 ExpectAndConsume(tok::eod);
764 return;
765 }
766 IdentifierInfo *II = Tok.getIdentifierInfo();
767 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
768 ConsumeToken();
769 } else {
770 SourceLocation StartLoc = Tok.getLocation();
771 EnterExpressionEvaluationContext Ctx(
774 if (!E.isUsable() || E.get()->containsErrors()) {
775 // Diagnostics were emitted during parsing. No action needed.
776 } else if (E.get()->getDependence() != ExprDependence::None) {
777 PP.Diag(StartLoc, diag::warn_pragma_debug_dependent_argument)
778 << E.get()->isTypeDependent()
779 << SourceRange(StartLoc, Tok.getLocation());
780 } else {
781 Actions.ActOnPragmaDump(E.get());
782 }
783 SkipUntil(tok::eod, StopBeforeMatch);
784 }
785 ExpectAndConsume(tok::eod);
786}
787
788void Parser::HandlePragmaWeak() {
789 assert(Tok.is(tok::annot_pragma_weak));
790 SourceLocation PragmaLoc = ConsumeAnnotationToken();
791 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
792 Tok.getLocation());
793 ConsumeToken(); // The weak name.
794}
795
796void Parser::HandlePragmaWeakAlias() {
797 assert(Tok.is(tok::annot_pragma_weakalias));
798 SourceLocation PragmaLoc = ConsumeAnnotationToken();
799 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
800 SourceLocation WeakNameLoc = Tok.getLocation();
801 ConsumeToken();
802 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
803 SourceLocation AliasNameLoc = Tok.getLocation();
804 ConsumeToken();
805 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
806 WeakNameLoc, AliasNameLoc);
807
808}
809
810void Parser::HandlePragmaRedefineExtname() {
811 assert(Tok.is(tok::annot_pragma_redefine_extname));
812 SourceLocation RedefLoc = ConsumeAnnotationToken();
813 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
814 SourceLocation RedefNameLoc = Tok.getLocation();
815 ConsumeToken();
816 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
817 SourceLocation AliasNameLoc = Tok.getLocation();
818 ConsumeToken();
819 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
820 RedefNameLoc, AliasNameLoc);
821}
822
823void Parser::HandlePragmaFPContract() {
824 assert(Tok.is(tok::annot_pragma_fp_contract));
825 tok::OnOffSwitch OOS =
826 static_cast<tok::OnOffSwitch>(
827 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
828
830 switch (OOS) {
831 case tok::OOS_ON:
833 break;
834 case tok::OOS_OFF:
836 break;
837 case tok::OOS_DEFAULT:
838 // According to ISO C99 standard chapter 7.3.4, the default value
839 // for the pragma is ``off'. '-fcomplex-arithmetic=basic',
840 // '-fcx-limited-range', '-fcx-fortran-rules' and
841 // '-fcomplex-arithmetic=improved' control the default value of these
842 // pragmas.
843 FPC = getLangOpts().getDefaultFPContractMode();
844 break;
845 }
846
847 SourceLocation PragmaLoc = ConsumeAnnotationToken();
848 Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
849}
850
851void Parser::HandlePragmaFloatControl() {
852 assert(Tok.is(tok::annot_pragma_float_control));
853
854 // The value that is held on the PragmaFloatControlStack encodes
855 // the PragmaFloatControl kind and the MSStackAction kind
856 // into a single 32-bit word. The MsStackAction is the high 16 bits
857 // and the FloatControl is the lower 16 bits. Use shift and bit-and
858 // to decode the parts.
859 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
861 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
863 SourceLocation PragmaLoc = ConsumeAnnotationToken();
864 Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
865}
866
867void Parser::HandlePragmaFEnvAccess() {
868 assert(Tok.is(tok::annot_pragma_fenv_access) ||
869 Tok.is(tok::annot_pragma_fenv_access_ms));
870 tok::OnOffSwitch OOS =
871 static_cast<tok::OnOffSwitch>(
872 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
873
874 bool IsEnabled;
875 switch (OOS) {
876 case tok::OOS_ON:
877 IsEnabled = true;
878 break;
879 case tok::OOS_OFF:
880 IsEnabled = false;
881 break;
882 case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
883 IsEnabled = false;
884 break;
885 }
886
887 SourceLocation PragmaLoc = ConsumeAnnotationToken();
888 Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
889}
890
891void Parser::HandlePragmaFEnvRound() {
892 assert(Tok.is(tok::annot_pragma_fenv_round));
893 auto RM = static_cast<llvm::RoundingMode>(
894 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
895
896 SourceLocation PragmaLoc = ConsumeAnnotationToken();
897 Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);
898}
899
900void Parser::HandlePragmaCXLimitedRange() {
901 assert(Tok.is(tok::annot_pragma_cx_limited_range));
902 tok::OnOffSwitch OOS = static_cast<tok::OnOffSwitch>(
903 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
904
906 switch (OOS) {
907 case tok::OOS_ON:
909 break;
910 case tok::OOS_OFF:
912 break;
913 case tok::OOS_DEFAULT:
914 // According to ISO C99 standard chapter 7.3.4, the default value
915 // for the pragma is ``off'. -fcomplex-arithmetic controls the default value
916 // of these pragmas.
917 Range = getLangOpts().getComplexRange();
918 break;
919 }
920
921 SourceLocation PragmaLoc = ConsumeAnnotationToken();
922 Actions.ActOnPragmaCXLimitedRange(PragmaLoc, Range);
923}
924
925StmtResult Parser::HandlePragmaCaptured()
926{
927 assert(Tok.is(tok::annot_pragma_captured));
928 ConsumeAnnotationToken();
929
930 if (Tok.isNot(tok::l_brace)) {
931 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
932 return StmtError();
933 }
934
935 SourceLocation Loc = Tok.getLocation();
936
937 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
939 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
940 /*NumParams=*/1);
941
942 StmtResult R = ParseCompoundStatement();
943 CapturedRegionScope.Exit();
944
945 if (R.isInvalid()) {
946 Actions.ActOnCapturedRegionError();
947 return StmtError();
948 }
949
950 return Actions.ActOnCapturedRegionEnd(R.get());
951}
952
953namespace {
954 enum OpenCLExtState : char {
955 Disable, Enable, Begin, End
956 };
957 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
958}
959
960void Parser::HandlePragmaOpenCLExtension() {
961 assert(Tok.is(tok::annot_pragma_opencl_extension));
962 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
963 auto State = Data->second;
964 auto Ident = Data->first;
965 SourceLocation NameLoc = Tok.getLocation();
966 ConsumeAnnotationToken();
967
968 auto &Opt = Actions.getOpenCLOptions();
969 auto Name = Ident->getName();
970 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
971 // overriding all previously issued extension directives, but only if the
972 // behavior is set to disable."
973 if (Name == "all") {
974 if (State == Disable)
975 Opt.disableAll();
976 else
977 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
978 } else if (State == Begin) {
979 if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
980 Opt.support(Name);
981 // FIXME: Default behavior of the extension pragma is not defined.
982 // Therefore, it should never be added by default.
983 Opt.acceptsPragma(Name);
984 }
985 } else if (State == End) {
986 // There is no behavior for this directive. We only accept this for
987 // backward compatibility.
988 } else if (!Opt.isKnown(Name) || !Opt.isWithPragma(Name))
989 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
990 else if (Opt.isSupportedExtension(Name, getLangOpts()))
991 Opt.enable(Name, State == Enable);
992 else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts()))
993 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
994 else
995 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
996}
997
998void Parser::HandlePragmaMSPointersToMembers() {
999 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
1000 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
1002 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
1003 SourceLocation PragmaLoc = ConsumeAnnotationToken();
1004 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
1005}
1006
1007void Parser::HandlePragmaMSVtorDisp() {
1008 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
1009 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
1011 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
1012 MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
1013 SourceLocation PragmaLoc = ConsumeAnnotationToken();
1014 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
1015}
1016
1017void Parser::HandlePragmaMSPragma() {
1018 assert(Tok.is(tok::annot_pragma_ms_pragma));
1019 // Grab the tokens out of the annotation and enter them into the stream.
1020 auto TheTokens =
1021 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
1022 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
1023 /*IsReinject=*/true);
1024 SourceLocation PragmaLocation = ConsumeAnnotationToken();
1025 assert(Tok.isAnyIdentifier());
1026 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
1027 PP.Lex(Tok); // pragma kind
1028
1029 // Figure out which #pragma we're dealing with. The switch has no default
1030 // because lex shouldn't emit the annotation token for unrecognized pragmas.
1031 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
1032 PragmaHandler Handler =
1033 llvm::StringSwitch<PragmaHandler>(PragmaName)
1034 .Case("data_seg", &Parser::HandlePragmaMSSegment)
1035 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
1036 .Case("const_seg", &Parser::HandlePragmaMSSegment)
1037 .Case("code_seg", &Parser::HandlePragmaMSSegment)
1038 .Case("section", &Parser::HandlePragmaMSSection)
1039 .Case("init_seg", &Parser::HandlePragmaMSInitSeg)
1040 .Case("strict_gs_check", &Parser::HandlePragmaMSStrictGuardStackCheck)
1041 .Case("function", &Parser::HandlePragmaMSFunction)
1042 .Case("alloc_text", &Parser::HandlePragmaMSAllocText)
1043 .Case("optimize", &Parser::HandlePragmaMSOptimize)
1044 .Case("intrinsic", &Parser::HandlePragmaMSIntrinsic);
1045
1046 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
1047 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
1048 // until eof (really end of line) to prevent follow-on errors.
1049 while (Tok.isNot(tok::eof))
1050 PP.Lex(Tok);
1051 PP.Lex(Tok);
1052 }
1053}
1054
1055bool Parser::HandlePragmaMSSection(StringRef PragmaName,
1056 SourceLocation PragmaLocation) {
1057 if (Tok.isNot(tok::l_paren)) {
1058 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
1059 return false;
1060 }
1061 PP.Lex(Tok); // (
1062 // Parsing code for pragma section
1063 if (Tok.isNot(tok::string_literal)) {
1064 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
1065 << PragmaName;
1066 return false;
1067 }
1069 if (StringResult.isInvalid())
1070 return false; // Already diagnosed.
1071 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
1072 if (SegmentName->getCharByteWidth() != 1) {
1073 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1074 << PragmaName;
1075 return false;
1076 }
1077 int SectionFlags = ASTContext::PSF_Read;
1078 bool SectionFlagsAreDefault = true;
1079 while (Tok.is(tok::comma)) {
1080 PP.Lex(Tok); // ,
1081 // Ignore "long" and "short".
1082 // They are undocumented, but widely used, section attributes which appear
1083 // to do nothing.
1084 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
1085 PP.Lex(Tok); // long/short
1086 continue;
1087 }
1088
1089 if (!Tok.isAnyIdentifier()) {
1090 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
1091 << PragmaName;
1092 return false;
1093 }
1095 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
1096 Tok.getIdentifierInfo()->getName())
1097 .Case("read", ASTContext::PSF_Read)
1098 .Case("write", ASTContext::PSF_Write)
1099 .Case("execute", ASTContext::PSF_Execute)
1100 .Case("shared", ASTContext::PSF_Invalid)
1101 .Case("nopage", ASTContext::PSF_Invalid)
1102 .Case("nocache", ASTContext::PSF_Invalid)
1103 .Case("discard", ASTContext::PSF_Invalid)
1104 .Case("remove", ASTContext::PSF_Invalid)
1105 .Default(ASTContext::PSF_None);
1106 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
1107 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
1108 ? diag::warn_pragma_invalid_specific_action
1109 : diag::warn_pragma_unsupported_action)
1110 << PragmaName << Tok.getIdentifierInfo()->getName();
1111 return false;
1112 }
1113 SectionFlags |= Flag;
1114 SectionFlagsAreDefault = false;
1115 PP.Lex(Tok); // Identifier
1116 }
1117 // If no section attributes are specified, the section will be marked as
1118 // read/write.
1119 if (SectionFlagsAreDefault)
1120 SectionFlags |= ASTContext::PSF_Write;
1121 if (Tok.isNot(tok::r_paren)) {
1122 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
1123 return false;
1124 }
1125 PP.Lex(Tok); // )
1126 if (Tok.isNot(tok::eof)) {
1127 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
1128 << PragmaName;
1129 return false;
1130 }
1131 PP.Lex(Tok); // eof
1132 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
1133 return true;
1134}
1135
1136bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
1137 SourceLocation PragmaLocation) {
1138 if (Tok.isNot(tok::l_paren)) {
1139 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
1140 return false;
1141 }
1142 PP.Lex(Tok); // (
1144 StringRef SlotLabel;
1145 if (Tok.isAnyIdentifier()) {
1146 StringRef PushPop = Tok.getIdentifierInfo()->getName();
1147 if (PushPop == "push")
1148 Action = Sema::PSK_Push;
1149 else if (PushPop == "pop")
1150 Action = Sema::PSK_Pop;
1151 else {
1152 PP.Diag(PragmaLocation,
1153 diag::warn_pragma_expected_section_push_pop_or_name)
1154 << PragmaName;
1155 return false;
1156 }
1157 if (Action != Sema::PSK_Reset) {
1158 PP.Lex(Tok); // push | pop
1159 if (Tok.is(tok::comma)) {
1160 PP.Lex(Tok); // ,
1161 // If we've got a comma, we either need a label or a string.
1162 if (Tok.isAnyIdentifier()) {
1163 SlotLabel = Tok.getIdentifierInfo()->getName();
1164 PP.Lex(Tok); // identifier
1165 if (Tok.is(tok::comma))
1166 PP.Lex(Tok);
1167 else if (Tok.isNot(tok::r_paren)) {
1168 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
1169 << PragmaName;
1170 return false;
1171 }
1172 }
1173 } else if (Tok.isNot(tok::r_paren)) {
1174 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
1175 return false;
1176 }
1177 }
1178 }
1179 // Grab the string literal for our section name.
1180 StringLiteral *SegmentName = nullptr;
1181 if (Tok.isNot(tok::r_paren)) {
1182 if (Tok.isNot(tok::string_literal)) {
1183 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
1184 diag::warn_pragma_expected_section_name :
1185 diag::warn_pragma_expected_section_label_or_name :
1186 diag::warn_pragma_expected_section_push_pop_or_name;
1187 PP.Diag(PragmaLocation, DiagID) << PragmaName;
1188 return false;
1189 }
1191 if (StringResult.isInvalid())
1192 return false; // Already diagnosed.
1193 SegmentName = cast<StringLiteral>(StringResult.get());
1194 if (SegmentName->getCharByteWidth() != 1) {
1195 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1196 << PragmaName;
1197 return false;
1198 }
1199 // Setting section "" has no effect
1200 if (SegmentName->getLength())
1201 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1202 }
1203 if (Tok.isNot(tok::r_paren)) {
1204 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
1205 return false;
1206 }
1207 PP.Lex(Tok); // )
1208 if (Tok.isNot(tok::eof)) {
1209 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
1210 << PragmaName;
1211 return false;
1212 }
1213 PP.Lex(Tok); // eof
1214 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
1215 SegmentName, PragmaName);
1216 return true;
1217}
1218
1219bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
1220 SourceLocation PragmaLocation) {
1221 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
1222 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
1223 return false;
1224 }
1225
1226 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1227 PragmaName))
1228 return false;
1229
1230 // Parse either the known section names or the string section name.
1231 StringLiteral *SegmentName = nullptr;
1232 if (Tok.isAnyIdentifier()) {
1233 auto *II = Tok.getIdentifierInfo();
1234 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
1235 .Case("compiler", "\".CRT$XCC\"")
1236 .Case("lib", "\".CRT$XCL\"")
1237 .Case("user", "\".CRT$XCU\"")
1238 .Default("");
1239
1240 if (!Section.empty()) {
1241 // Pretend the user wrote the appropriate string literal here.
1242 Token Toks[1];
1243 Toks[0].startToken();
1244 Toks[0].setKind(tok::string_literal);
1245 Toks[0].setLocation(Tok.getLocation());
1246 Toks[0].setLiteralData(Section.data());
1247 Toks[0].setLength(Section.size());
1248 SegmentName =
1249 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
1250 PP.Lex(Tok);
1251 }
1252 } else if (Tok.is(tok::string_literal)) {
1254 if (StringResult.isInvalid())
1255 return false;
1256 SegmentName = cast<StringLiteral>(StringResult.get());
1257 if (SegmentName->getCharByteWidth() != 1) {
1258 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1259 << PragmaName;
1260 return false;
1261 }
1262 // FIXME: Add support for the '[, func-name]' part of the pragma.
1263 }
1264
1265 if (!SegmentName) {
1266 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
1267 return false;
1268 }
1269
1270 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1271 PragmaName) ||
1272 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1273 PragmaName))
1274 return false;
1275
1276 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
1277 return true;
1278}
1279
1280bool Parser::HandlePragmaMSStrictGuardStackCheck(
1281 StringRef PragmaName, SourceLocation PragmaLocation) {
1282 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1283 PragmaName))
1284 return false;
1285
1287 if (Tok.is(tok::identifier)) {
1288 StringRef PushPop = Tok.getIdentifierInfo()->getName();
1289 if (PushPop == "push") {
1290 PP.Lex(Tok);
1291 Action = Sema::PSK_Push;
1292 if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_punc,
1293 PragmaName))
1294 return false;
1295 } else if (PushPop == "pop") {
1296 PP.Lex(Tok);
1297 Action = Sema::PSK_Pop;
1298 }
1299 }
1300
1301 bool Value = false;
1302 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
1303 const IdentifierInfo *II = Tok.getIdentifierInfo();
1304 if (II && II->isStr("off")) {
1305 PP.Lex(Tok);
1306 Value = false;
1307 } else if (II && II->isStr("on")) {
1308 PP.Lex(Tok);
1309 Value = true;
1310 } else {
1311 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1312 << PragmaName;
1313 return false;
1314 }
1315 }
1316
1317 // Finish the pragma: ')' $
1318 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1319 PragmaName))
1320 return false;
1321
1322 if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1323 PragmaName))
1324 return false;
1325
1326 Actions.ActOnPragmaMSStrictGuardStackCheck(PragmaLocation, Action, Value);
1327 return true;
1328}
1329
1330bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
1331 SourceLocation PragmaLocation) {
1332 Token FirstTok = Tok;
1333 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1334 PragmaName))
1335 return false;
1336
1337 StringRef Section;
1338 if (Tok.is(tok::string_literal)) {
1340 if (StringResult.isInvalid())
1341 return false; // Already diagnosed.
1342 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
1343 if (SegmentName->getCharByteWidth() != 1) {
1344 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1345 << PragmaName;
1346 return false;
1347 }
1348 Section = SegmentName->getString();
1349 } else if (Tok.is(tok::identifier)) {
1350 Section = Tok.getIdentifierInfo()->getName();
1351 PP.Lex(Tok);
1352 } else {
1353 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
1354 << PragmaName;
1355 return false;
1356 }
1357
1358 if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
1359 PragmaName))
1360 return false;
1361
1362 SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> Functions;
1363 while (true) {
1364 if (Tok.isNot(tok::identifier)) {
1365 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1366 << PragmaName;
1367 return false;
1368 }
1369
1370 IdentifierInfo *II = Tok.getIdentifierInfo();
1371 Functions.emplace_back(II, Tok.getLocation());
1372
1373 PP.Lex(Tok);
1374 if (Tok.isNot(tok::comma))
1375 break;
1376 PP.Lex(Tok);
1377 }
1378
1379 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1380 PragmaName) ||
1381 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1382 PragmaName))
1383 return false;
1384
1385 Actions.ActOnPragmaMSAllocText(FirstTok.getLocation(), Section, Functions);
1386 return true;
1387}
1388
1389static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
1390 StringRef Str = PragmaName.getIdentifierInfo()->getName();
1391 std::string ClangLoopStr("clang loop ");
1392 if (Str == "loop" && Option.getIdentifierInfo())
1393 ClangLoopStr += Option.getIdentifierInfo()->getName();
1394 return std::string(llvm::StringSwitch<StringRef>(Str)
1395 .Case("loop", ClangLoopStr)
1396 .Case("unroll_and_jam", Str)
1397 .Case("unroll", Str)
1398 .Default(""));
1399}
1400
1401bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
1402 assert(Tok.is(tok::annot_pragma_loop_hint));
1403 PragmaLoopHintInfo *Info =
1404 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1405
1406 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1407 Hint.PragmaNameLoc = new (Actions.Context)
1408 IdentifierLoc(Info->PragmaName.getLocation(), PragmaNameInfo);
1409
1410 // It is possible that the loop hint has no option identifier, such as
1411 // #pragma unroll(4).
1412 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1413 ? Info->Option.getIdentifierInfo()
1414 : nullptr;
1415 Hint.OptionLoc = new (Actions.Context)
1416 IdentifierLoc(Info->Option.getLocation(), OptionInfo);
1417
1418 llvm::ArrayRef<Token> Toks = Info->Toks;
1419
1420 // Return a valid hint if pragma unroll or nounroll were specified
1421 // without an argument.
1422 auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1423 .Cases("unroll", "nounroll", "unroll_and_jam",
1424 "nounroll_and_jam", true)
1425 .Default(false);
1426
1427 if (Toks.empty() && IsLoopHint) {
1428 ConsumeAnnotationToken();
1429 Hint.Range = Info->PragmaName.getLocation();
1430 return true;
1431 }
1432
1433 // The constant expression is always followed by an eof token, which increases
1434 // the TokSize by 1.
1435 assert(!Toks.empty() &&
1436 "PragmaLoopHintInfo::Toks must contain at least one token.");
1437
1438 // If no option is specified the argument is assumed to be a constant expr.
1439 bool OptionUnroll = false;
1440 bool OptionUnrollAndJam = false;
1441 bool OptionDistribute = false;
1442 bool OptionPipelineDisabled = false;
1443 bool StateOption = false;
1444 if (OptionInfo) { // Pragma Unroll does not specify an option.
1445 OptionUnroll = OptionInfo->isStr("unroll");
1446 OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
1447 OptionDistribute = OptionInfo->isStr("distribute");
1448 OptionPipelineDisabled = OptionInfo->isStr("pipeline");
1449 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1450 .Case("vectorize", true)
1451 .Case("interleave", true)
1452 .Case("vectorize_predicate", true)
1453 .Default(false) ||
1454 OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
1455 OptionPipelineDisabled;
1456 }
1457
1458 bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
1459 !OptionDistribute && !OptionPipelineDisabled;
1460 // Verify loop hint has an argument.
1461 if (Toks[0].is(tok::eof)) {
1462 ConsumeAnnotationToken();
1463 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
1464 << /*StateArgument=*/StateOption
1465 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1466 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1467 return false;
1468 }
1469
1470 // Validate the argument.
1471 if (StateOption) {
1472 ConsumeAnnotationToken();
1473 SourceLocation StateLoc = Toks[0].getLocation();
1474 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1475
1476 bool Valid = StateInfo &&
1477 llvm::StringSwitch<bool>(StateInfo->getName())
1478 .Case("disable", true)
1479 .Case("enable", !OptionPipelineDisabled)
1480 .Case("full", OptionUnroll || OptionUnrollAndJam)
1481 .Case("assume_safety", AssumeSafetyArg)
1482 .Default(false);
1483 if (!Valid) {
1484 if (OptionPipelineDisabled) {
1485 Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
1486 } else {
1487 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
1488 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1489 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1490 }
1491 return false;
1492 }
1493 if (Toks.size() > 2)
1494 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1495 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1496 Hint.StateLoc = new (Actions.Context) IdentifierLoc(StateLoc, StateInfo);
1497 } else if (OptionInfo && OptionInfo->getName() == "vectorize_width") {
1498 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1499 /*IsReinject=*/false);
1500 ConsumeAnnotationToken();
1501
1502 SourceLocation StateLoc = Toks[0].getLocation();
1503 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1504 StringRef IsScalableStr = StateInfo ? StateInfo->getName() : "";
1505
1506 // Look for vectorize_width(fixed|scalable)
1507 if (IsScalableStr == "scalable" || IsScalableStr == "fixed") {
1508 PP.Lex(Tok); // Identifier
1509
1510 if (Toks.size() > 2) {
1511 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1512 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1513 while (Tok.isNot(tok::eof))
1515 }
1516
1517 Hint.StateLoc = new (Actions.Context) IdentifierLoc(StateLoc, StateInfo);
1518
1519 ConsumeToken(); // Consume the constant expression eof terminator.
1520 } else {
1521 // Enter constant expression including eof terminator into token stream.
1523
1524 if (R.isInvalid() && !Tok.is(tok::comma))
1525 Diag(Toks[0].getLocation(),
1526 diag::note_pragma_loop_invalid_vectorize_option);
1527
1528 bool Arg2Error = false;
1529 if (Tok.is(tok::comma)) {
1530 PP.Lex(Tok); // ,
1531
1532 StateInfo = Tok.getIdentifierInfo();
1533 IsScalableStr = StateInfo->getName();
1534
1535 if (IsScalableStr != "scalable" && IsScalableStr != "fixed") {
1536 Diag(Tok.getLocation(),
1537 diag::err_pragma_loop_invalid_vectorize_option);
1538 Arg2Error = true;
1539 } else
1540 Hint.StateLoc =
1541 new (Actions.Context) IdentifierLoc(StateLoc, StateInfo);
1542
1543 PP.Lex(Tok); // Identifier
1544 }
1545
1546 // Tokens following an error in an ill-formed constant expression will
1547 // remain in the token stream and must be removed.
1548 if (Tok.isNot(tok::eof)) {
1549 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1550 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1551 while (Tok.isNot(tok::eof))
1553 }
1554
1555 ConsumeToken(); // Consume the constant expression eof terminator.
1556
1557 if (Arg2Error || R.isInvalid() ||
1558 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(),
1559 /*AllowZero=*/false))
1560 return false;
1561
1562 // Argument is a constant expression with an integer type.
1563 Hint.ValueExpr = R.get();
1564 }
1565 } else {
1566 // Enter constant expression including eof terminator into token stream.
1567 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1568 /*IsReinject=*/false);
1569 ConsumeAnnotationToken();
1571
1572 // Tokens following an error in an ill-formed constant expression will
1573 // remain in the token stream and must be removed.
1574 if (Tok.isNot(tok::eof)) {
1575 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1576 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1577 while (Tok.isNot(tok::eof))
1579 }
1580
1581 ConsumeToken(); // Consume the constant expression eof terminator.
1582
1583 if (R.isInvalid() ||
1584 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation(),
1585 /*AllowZero=*/true))
1586 return false;
1587
1588 // Argument is a constant expression with an integer type.
1589 Hint.ValueExpr = R.get();
1590 }
1591
1592 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
1593 Info->Toks.back().getLocation());
1594 return true;
1595}
1596
1597namespace {
1598struct PragmaAttributeInfo {
1599 enum ActionType { Push, Pop, Attribute };
1600 ParsedAttributes &Attributes;
1601 ActionType Action;
1602 const IdentifierInfo *Namespace = nullptr;
1603 ArrayRef<Token> Tokens;
1604
1605 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1606};
1607
1608#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1609
1610} // end anonymous namespace
1611
1612static StringRef getIdentifier(const Token &Tok) {
1613 if (Tok.is(tok::identifier))
1614 return Tok.getIdentifierInfo()->getName();
1615 const char *S = tok::getKeywordSpelling(Tok.getKind());
1616 if (!S)
1617 return "";
1618 return S;
1619}
1620
1622 using namespace attr;
1623 switch (Rule) {
1624#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1625 case Value: \
1626 return IsAbstract;
1627#include "clang/Basic/AttrSubMatchRulesList.inc"
1628 }
1629 llvm_unreachable("Invalid attribute subject match rule");
1630 return false;
1631}
1632
1634 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1635 SourceLocation SubRuleLoc) {
1636 auto Diagnostic =
1637 PRef.Diag(SubRuleLoc,
1638 diag::err_pragma_attribute_expected_subject_sub_identifier)
1639 << PrimaryRuleName;
1640 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1641 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1642 else
1643 Diagnostic << /*SubRulesSupported=*/0;
1644}
1645
1647 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1648 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1649
1650 auto Diagnostic =
1651 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1652 << SubRuleName << PrimaryRuleName;
1653 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1654 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1655 else
1656 Diagnostic << /*SubRulesSupported=*/0;
1657}
1658
1659bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1660 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1661 SourceLocation &LastMatchRuleEndLoc) {
1662 bool IsAny = false;
1663 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1664 if (getIdentifier(Tok) == "any") {
1665 AnyLoc = ConsumeToken();
1666 IsAny = true;
1667 if (AnyParens.expectAndConsume())
1668 return true;
1669 }
1670
1671 do {
1672 // Parse the subject matcher rule.
1673 StringRef Name = getIdentifier(Tok);
1674 if (Name.empty()) {
1675 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1676 return true;
1677 }
1678 std::pair<std::optional<attr::SubjectMatchRule>,
1679 std::optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1680 Rule = isAttributeSubjectMatchRule(Name);
1681 if (!Rule.first) {
1682 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1683 return true;
1684 }
1685 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1686 SourceLocation RuleLoc = ConsumeToken();
1687
1688 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1689 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1690 if (Parens.expectAndConsume())
1691 return true;
1692 } else if (Parens.consumeOpen()) {
1693 if (!SubjectMatchRules
1694 .insert(
1695 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1696 .second)
1697 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1698 << Name
1699 << FixItHint::CreateRemoval(SourceRange(
1700 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1701 LastMatchRuleEndLoc = RuleLoc;
1702 continue;
1703 }
1704
1705 // Parse the sub-rules.
1706 StringRef SubRuleName = getIdentifier(Tok);
1707 if (SubRuleName.empty()) {
1708 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1709 Tok.getLocation());
1710 return true;
1711 }
1712 attr::SubjectMatchRule SubRule;
1713 if (SubRuleName == "unless") {
1714 SourceLocation SubRuleLoc = ConsumeToken();
1715 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1716 if (Parens.expectAndConsume())
1717 return true;
1718 SubRuleName = getIdentifier(Tok);
1719 if (SubRuleName.empty()) {
1720 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1721 SubRuleLoc);
1722 return true;
1723 }
1724 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1725 if (!SubRuleOrNone) {
1726 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1727 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1728 SubRuleUnlessName, SubRuleLoc);
1729 return true;
1730 }
1731 SubRule = *SubRuleOrNone;
1732 ConsumeToken();
1733 if (Parens.consumeClose())
1734 return true;
1735 } else {
1736 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1737 if (!SubRuleOrNone) {
1738 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1739 SubRuleName, Tok.getLocation());
1740 return true;
1741 }
1742 SubRule = *SubRuleOrNone;
1743 ConsumeToken();
1744 }
1745 SourceLocation RuleEndLoc = Tok.getLocation();
1746 LastMatchRuleEndLoc = RuleEndLoc;
1747 if (Parens.consumeClose())
1748 return true;
1749 if (!SubjectMatchRules
1750 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1751 .second) {
1752 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1754 << FixItHint::CreateRemoval(SourceRange(
1755 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1756 continue;
1757 }
1758 } while (IsAny && TryConsumeToken(tok::comma));
1759
1760 if (IsAny)
1761 if (AnyParens.consumeClose())
1762 return true;
1763
1764 return false;
1765}
1766
1767namespace {
1768
1769/// Describes the stage at which attribute subject rule parsing was interrupted.
1770enum class MissingAttributeSubjectRulesRecoveryPoint {
1771 Comma,
1772 ApplyTo,
1773 Equals,
1774 Any,
1775 None,
1776};
1777
1778MissingAttributeSubjectRulesRecoveryPoint
1779getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1780 if (const auto *II = Tok.getIdentifierInfo()) {
1781 if (II->isStr("apply_to"))
1782 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1783 if (II->isStr("any"))
1784 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1785 }
1786 if (Tok.is(tok::equal))
1787 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1788 return MissingAttributeSubjectRulesRecoveryPoint::None;
1789}
1790
1791/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1792/// suggests the possible attribute subject rules in a fix-it together with
1793/// any other missing tokens.
1794DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1795 unsigned DiagID, ParsedAttributes &Attrs,
1796 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1798 if (Loc.isInvalid())
1799 Loc = PRef.getCurToken().getLocation();
1800 auto Diagnostic = PRef.Diag(Loc, DiagID);
1801 std::string FixIt;
1802 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1803 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1804 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1805 FixIt = ", ";
1806 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1807 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1808 FixIt += "apply_to";
1809 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1810 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1811 FixIt += " = ";
1812 SourceRange FixItRange(Loc);
1813 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1814 // Gather the subject match rules that are supported by the attribute.
1815 // Add all the possible rules initially.
1816 llvm::BitVector IsMatchRuleAvailable(attr::SubjectMatchRule_Last + 1, true);
1817 // Remove the ones that are not supported by any of the attributes.
1818 for (const ParsedAttr &Attribute : Attrs) {
1820 Attribute.getMatchRules(PRef.getLangOpts(), MatchRules);
1821 llvm::BitVector IsSupported(attr::SubjectMatchRule_Last + 1);
1822 for (const auto &Rule : MatchRules) {
1823 // Ensure that the missing rule is reported in the fix-it only when it's
1824 // supported in the current language mode.
1825 if (!Rule.second)
1826 continue;
1827 IsSupported[Rule.first] = true;
1828 }
1829 IsMatchRuleAvailable &= IsSupported;
1830 }
1831 if (IsMatchRuleAvailable.count() == 0) {
1832 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1833 // placeholders will be supported by the fix-its.
1834 return Diagnostic;
1835 }
1836 FixIt += "any(";
1837 bool NeedsComma = false;
1838 for (unsigned I = 0; I <= attr::SubjectMatchRule_Last; I++) {
1839 if (!IsMatchRuleAvailable[I])
1840 continue;
1841 if (NeedsComma)
1842 FixIt += ", ";
1843 else
1844 NeedsComma = true;
1846 static_cast<attr::SubjectMatchRule>(I));
1847 }
1848 FixIt += ")";
1849 // Check if we need to remove the range
1850 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1851 FixItRange.setEnd(PRef.getCurToken().getLocation());
1852 }
1853 if (FixItRange.getBegin() == FixItRange.getEnd())
1854 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1855 else
1857 CharSourceRange::getCharRange(FixItRange), FixIt);
1858 return Diagnostic;
1859}
1860
1861} // end anonymous namespace
1862
1863void Parser::HandlePragmaAttribute() {
1864 assert(Tok.is(tok::annot_pragma_attribute) &&
1865 "Expected #pragma attribute annotation token");
1866 SourceLocation PragmaLoc = Tok.getLocation();
1867 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1868 if (Info->Action == PragmaAttributeInfo::Pop) {
1869 ConsumeAnnotationToken();
1870 Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
1871 return;
1872 }
1873 // Parse the actual attribute with its arguments.
1874 assert((Info->Action == PragmaAttributeInfo::Push ||
1875 Info->Action == PragmaAttributeInfo::Attribute) &&
1876 "Unexpected #pragma attribute command");
1877
1878 if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
1879 ConsumeAnnotationToken();
1880 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1881 return;
1882 }
1883
1884 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
1885 /*IsReinject=*/false);
1886 ConsumeAnnotationToken();
1887
1888 ParsedAttributes &Attrs = Info->Attributes;
1889 Attrs.clearListOnly();
1890
1891 auto SkipToEnd = [this]() {
1892 SkipUntil(tok::eof, StopBeforeMatch);
1893 ConsumeToken();
1894 };
1895
1896 if ((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
1897 Tok.isRegularKeywordAttribute()) {
1898 // Parse the CXX11 style attribute.
1899 ParseCXX11AttributeSpecifier(Attrs);
1900 } else if (Tok.is(tok::kw___attribute)) {
1901 ConsumeToken();
1902 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1903 "attribute"))
1904 return SkipToEnd();
1905 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1906 return SkipToEnd();
1907
1908 // FIXME: The practical usefulness of completion here is limited because
1909 // we only get here if the line has balanced parens.
1910 if (Tok.is(tok::code_completion)) {
1911 cutOffParsing();
1912 // FIXME: suppress completion of unsupported attributes?
1913 Actions.CodeCompletion().CodeCompleteAttribute(
1915 return SkipToEnd();
1916 }
1917
1918 // Parse the comma-separated list of attributes.
1919 do {
1920 if (Tok.isNot(tok::identifier)) {
1921 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1922 SkipToEnd();
1923 return;
1924 }
1925 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1926 SourceLocation AttrNameLoc = ConsumeToken();
1927
1928 if (Tok.isNot(tok::l_paren))
1929 Attrs.addNew(AttrName, AttrNameLoc, AttributeScopeInfo(), nullptr, 0,
1930 ParsedAttr::Form::GNU());
1931 else
1932 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1933 /*ScopeName=*/nullptr,
1934 /*ScopeLoc=*/SourceLocation(),
1935 ParsedAttr::Form::GNU(),
1936 /*Declarator=*/nullptr);
1937 } while (TryConsumeToken(tok::comma));
1938
1939 if (ExpectAndConsume(tok::r_paren))
1940 return SkipToEnd();
1941 if (ExpectAndConsume(tok::r_paren))
1942 return SkipToEnd();
1943 } else if (Tok.is(tok::kw___declspec)) {
1944 ParseMicrosoftDeclSpecs(Attrs);
1945 } else {
1946 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1947 if (Tok.getIdentifierInfo()) {
1948 // If we suspect that this is an attribute suggest the use of
1949 // '__attribute__'.
1951 Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1953 SourceLocation InsertStartLoc = Tok.getLocation();
1954 ConsumeToken();
1955 if (Tok.is(tok::l_paren)) {
1957 SkipUntil(tok::r_paren, StopBeforeMatch);
1958 if (Tok.isNot(tok::r_paren))
1959 return SkipToEnd();
1960 }
1961 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1962 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1963 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1964 }
1965 }
1966 SkipToEnd();
1967 return;
1968 }
1969
1970 if (Attrs.empty() || Attrs.begin()->isInvalid()) {
1971 SkipToEnd();
1972 return;
1973 }
1974
1975 for (const ParsedAttr &Attribute : Attrs) {
1976 if (!Attribute.isSupportedByPragmaAttribute()) {
1977 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1978 << Attribute;
1979 SkipToEnd();
1980 return;
1981 }
1982 }
1983
1984 // Parse the subject-list.
1985 if (!TryConsumeToken(tok::comma)) {
1986 createExpectedAttributeSubjectRulesTokenDiagnostic(
1987 diag::err_expected, Attrs,
1988 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1989 << tok::comma;
1990 SkipToEnd();
1991 return;
1992 }
1993
1994 if (Tok.isNot(tok::identifier)) {
1995 createExpectedAttributeSubjectRulesTokenDiagnostic(
1996 diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
1997 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1998 SkipToEnd();
1999 return;
2000 }
2001 const IdentifierInfo *II = Tok.getIdentifierInfo();
2002 if (!II->isStr("apply_to")) {
2003 createExpectedAttributeSubjectRulesTokenDiagnostic(
2004 diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
2005 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
2006 SkipToEnd();
2007 return;
2008 }
2009 ConsumeToken();
2010
2011 if (!TryConsumeToken(tok::equal)) {
2012 createExpectedAttributeSubjectRulesTokenDiagnostic(
2013 diag::err_expected, Attrs,
2014 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
2015 << tok::equal;
2016 SkipToEnd();
2017 return;
2018 }
2019
2020 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
2021 SourceLocation AnyLoc, LastMatchRuleEndLoc;
2022 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
2023 LastMatchRuleEndLoc)) {
2024 SkipToEnd();
2025 return;
2026 }
2027
2028 // Tokens following an ill-formed attribute will remain in the token stream
2029 // and must be removed.
2030 if (Tok.isNot(tok::eof)) {
2031 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
2032 SkipToEnd();
2033 return;
2034 }
2035
2036 // Consume the eof terminator token.
2037 ConsumeToken();
2038
2039 // Handle a mixed push/attribute by desurging to a push, then an attribute.
2040 if (Info->Action == PragmaAttributeInfo::Push)
2041 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
2042
2043 for (ParsedAttr &Attribute : Attrs) {
2044 Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
2045 SubjectMatchRules);
2046 }
2047}
2048
2049// #pragma GCC visibility comes in two variants:
2050// 'push' '(' [visibility] ')'
2051// 'pop'
2052void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
2053 PragmaIntroducer Introducer,
2054 Token &VisTok) {
2055 SourceLocation VisLoc = VisTok.getLocation();
2056
2057 Token Tok;
2059
2060 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
2061
2062 const IdentifierInfo *VisType;
2063 if (PushPop && PushPop->isStr("pop")) {
2064 VisType = nullptr;
2065 } else if (PushPop && PushPop->isStr("push")) {
2067 if (Tok.isNot(tok::l_paren)) {
2068 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
2069 << "visibility";
2070 return;
2071 }
2073 VisType = Tok.getIdentifierInfo();
2074 if (!VisType) {
2075 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2076 << "visibility";
2077 return;
2078 }
2080 if (Tok.isNot(tok::r_paren)) {
2081 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
2082 << "visibility";
2083 return;
2084 }
2085 } else {
2086 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2087 << "visibility";
2088 return;
2089 }
2090 SourceLocation EndLoc = Tok.getLocation();
2092 if (Tok.isNot(tok::eod)) {
2093 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2094 << "visibility";
2095 return;
2096 }
2097
2098 auto Toks = std::make_unique<Token[]>(1);
2099 Toks[0].startToken();
2100 Toks[0].setKind(tok::annot_pragma_vis);
2101 Toks[0].setLocation(VisLoc);
2102 Toks[0].setAnnotationEndLoc(EndLoc);
2103 Toks[0].setAnnotationValue(
2104 const_cast<void *>(static_cast<const void *>(VisType)));
2105 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
2106 /*IsReinject=*/false);
2107}
2108
2109// #pragma pack(...) comes in the following delicious flavors:
2110// pack '(' [integer] ')'
2111// pack '(' 'show' ')'
2112// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
2113// pack '(' 'packed' | 'full' | 'twobyte' | 'reset' ')' with -fzos-extensions
2114void PragmaPackHandler::HandlePragma(Preprocessor &PP,
2115 PragmaIntroducer Introducer,
2116 Token &PackTok) {
2117 SourceLocation PackLoc = PackTok.getLocation();
2118
2119 Token Tok;
2120 PP.Lex(Tok);
2121 if (Tok.isNot(tok::l_paren)) {
2122 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
2123 return;
2124 }
2125
2127 StringRef SlotLabel;
2128 Token Alignment;
2129 Alignment.startToken();
2130 PP.Lex(Tok);
2131 if (Tok.is(tok::numeric_constant)) {
2132 Alignment = Tok;
2133
2134 PP.Lex(Tok);
2135
2136 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
2137 // the push/pop stack.
2138 // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)
2139 Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack)
2141 : Sema::PSK_Set;
2142 } else if (Tok.is(tok::identifier)) {
2143 // Map pragma pack options to pack (integer).
2144 auto MapPack = [&](const char *Literal) {
2145 Action = Sema::PSK_Push_Set;
2146 Alignment = Tok;
2147 Alignment.setKind(tok::numeric_constant);
2148 Alignment.setLiteralData(Literal);
2149 Alignment.setLength(1);
2150 };
2151
2152 const IdentifierInfo *II = Tok.getIdentifierInfo();
2153 if (II->isStr("show")) {
2154 Action = Sema::PSK_Show;
2155 PP.Lex(Tok);
2156 } else if (II->isStr("packed") && PP.getLangOpts().ZOSExt) {
2157 // #pragma pack(packed) is the same as #pragma pack(1)
2158 MapPack("1");
2159 PP.Lex(Tok);
2160 } else if (II->isStr("full") && PP.getLangOpts().ZOSExt) {
2161 // #pragma pack(full) is the same as #pragma pack(4)
2162 MapPack("4");
2163 PP.Lex(Tok);
2164 } else if (II->isStr("twobyte") && PP.getLangOpts().ZOSExt) {
2165 // #pragma pack(twobyte) is the same as #pragma pack(2)
2166 MapPack("2");
2167 PP.Lex(Tok);
2168 } else if (II->isStr("reset") && PP.getLangOpts().ZOSExt) {
2169 // #pragma pack(reset) is the same as #pragma pack(pop) on XL
2170 Action = Sema::PSK_Pop;
2171 PP.Lex(Tok);
2172 } else {
2173 if (II->isStr("push")) {
2174 Action = Sema::PSK_Push;
2175 } else if (II->isStr("pop")) {
2176 Action = Sema::PSK_Pop;
2177 } else {
2178 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
2179 return;
2180 }
2181 PP.Lex(Tok);
2182
2183 if (Tok.is(tok::comma)) {
2184 PP.Lex(Tok);
2185
2186 if (Tok.is(tok::numeric_constant)) {
2187 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
2188 Alignment = Tok;
2189
2190 PP.Lex(Tok);
2191 } else if (Tok.is(tok::identifier)) {
2192 SlotLabel = Tok.getIdentifierInfo()->getName();
2193 PP.Lex(Tok);
2194
2195 if (Tok.is(tok::comma)) {
2196 PP.Lex(Tok);
2197
2198 if (Tok.isNot(tok::numeric_constant)) {
2199 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2200 return;
2201 }
2202
2203 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
2204 Alignment = Tok;
2205
2206 PP.Lex(Tok);
2207 }
2208 } else {
2209 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2210 return;
2211 }
2212 }
2213 }
2214 } else if (PP.getLangOpts().ApplePragmaPack ||
2215 PP.getLangOpts().XLPragmaPack) {
2216 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
2217 // the push/pop stack.
2218 // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma
2219 // pack(pop).
2220 Action = Sema::PSK_Pop;
2221 }
2222
2223 if (Tok.isNot(tok::r_paren)) {
2224 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
2225 return;
2226 }
2227
2228 SourceLocation RParenLoc = Tok.getLocation();
2229 PP.Lex(Tok);
2230 if (Tok.isNot(tok::eod)) {
2231 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
2232 return;
2233 }
2234
2235 Sema::PragmaPackInfo *Info =
2237 Info->Action = Action;
2238 Info->SlotLabel = SlotLabel;
2239 Info->Alignment = Alignment;
2240
2242 1);
2243 Toks[0].startToken();
2244 Toks[0].setKind(tok::annot_pragma_pack);
2245 Toks[0].setLocation(PackLoc);
2246 Toks[0].setAnnotationEndLoc(RParenLoc);
2247 Toks[0].setAnnotationValue(static_cast<void*>(Info));
2248 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2249 /*IsReinject=*/false);
2250}
2251
2252// #pragma ms_struct on
2253// #pragma ms_struct off
2254void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
2255 PragmaIntroducer Introducer,
2256 Token &MSStructTok) {
2258
2259 Token Tok;
2260 PP.Lex(Tok);
2261 if (Tok.isNot(tok::identifier)) {
2262 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2263 return;
2264 }
2265 SourceLocation EndLoc = Tok.getLocation();
2266 const IdentifierInfo *II = Tok.getIdentifierInfo();
2267 if (II->isStr("on")) {
2268 Kind = PMSST_ON;
2269 PP.Lex(Tok);
2270 }
2271 else if (II->isStr("off") || II->isStr("reset"))
2272 PP.Lex(Tok);
2273 else {
2274 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2275 return;
2276 }
2277
2278 if (Tok.isNot(tok::eod)) {
2279 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2280 << "ms_struct";
2281 return;
2282 }
2283
2285 1);
2286 Toks[0].startToken();
2287 Toks[0].setKind(tok::annot_pragma_msstruct);
2288 Toks[0].setLocation(MSStructTok.getLocation());
2289 Toks[0].setAnnotationEndLoc(EndLoc);
2290 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2291 static_cast<uintptr_t>(Kind)));
2292 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2293 /*IsReinject=*/false);
2294}
2295
2296// #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
2297void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
2298 PragmaIntroducer Introducer,
2299 Token &FirstToken) {
2300
2301 Token Tok;
2302 auto SecKind = PragmaClangSectionKind::Invalid;
2303
2304 PP.Lex(Tok); // eat 'section'
2305 while (Tok.isNot(tok::eod)) {
2306 if (Tok.isNot(tok::identifier)) {
2307 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2308 return;
2309 }
2310
2311 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
2312 if (SecType->isStr("bss"))
2314 else if (SecType->isStr("data"))
2316 else if (SecType->isStr("rodata"))
2318 else if (SecType->isStr("relro"))
2320 else if (SecType->isStr("text"))
2322 else {
2323 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2324 return;
2325 }
2326
2327 SourceLocation PragmaLocation = Tok.getLocation();
2328 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
2329 if (Tok.isNot(tok::equal)) {
2330 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal)
2331 << SecKind;
2332 return;
2333 }
2334
2335 std::string SecName;
2336 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
2337 return;
2338
2339 Actions.ActOnPragmaClangSection(PragmaLocation,
2340 (SecName.size()
2343 SecKind, SecName);
2344 }
2345}
2346
2347// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
2348// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
2349// #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
2350static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
2351 bool IsOptions) {
2352 Token Tok;
2353
2354 if (IsOptions) {
2355 PP.Lex(Tok);
2356 if (Tok.isNot(tok::identifier) ||
2357 !Tok.getIdentifierInfo()->isStr("align")) {
2358 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
2359 return;
2360 }
2361 }
2362
2363 PP.Lex(Tok);
2364 if (PP.getLangOpts().XLPragmaPack) {
2365 if (Tok.isNot(tok::l_paren)) {
2366 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";
2367 return;
2368 }
2369 } else if (Tok.isNot(tok::equal)) {
2370 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
2371 << IsOptions;
2372 return;
2373 }
2374
2375 PP.Lex(Tok);
2376 if (Tok.isNot(tok::identifier)) {
2377 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2378 << (IsOptions ? "options" : "align");
2379 return;
2380 }
2381
2383 const IdentifierInfo *II = Tok.getIdentifierInfo();
2384 if (II->isStr("native"))
2386 else if (II->isStr("natural"))
2388 else if (II->isStr("packed"))
2390 else if (II->isStr("power"))
2392 else if (II->isStr("mac68k"))
2394 else if (II->isStr("reset"))
2396 else {
2397 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
2398 << IsOptions;
2399 return;
2400 }
2401
2402 if (PP.getLangOpts().XLPragmaPack) {
2403 PP.Lex(Tok);
2404 if (Tok.isNot(tok::r_paren)) {
2405 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";
2406 return;
2407 }
2408 }
2409
2410 SourceLocation EndLoc = Tok.getLocation();
2411 PP.Lex(Tok);
2412 if (Tok.isNot(tok::eod)) {
2413 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2414 << (IsOptions ? "options" : "align");
2415 return;
2416 }
2417
2419 1);
2420 Toks[0].startToken();
2421 Toks[0].setKind(tok::annot_pragma_align);
2422 Toks[0].setLocation(FirstTok.getLocation());
2423 Toks[0].setAnnotationEndLoc(EndLoc);
2424 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2425 static_cast<uintptr_t>(Kind)));
2426 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2427 /*IsReinject=*/false);
2428}
2429
2430void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
2431 PragmaIntroducer Introducer,
2432 Token &AlignTok) {
2433 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
2434}
2435
2436void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
2437 PragmaIntroducer Introducer,
2438 Token &OptionsTok) {
2439 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
2440}
2441
2442// #pragma unused(identifier)
2443void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
2444 PragmaIntroducer Introducer,
2445 Token &UnusedTok) {
2446 // FIXME: Should we be expanding macros here? My guess is no.
2447 SourceLocation UnusedLoc = UnusedTok.getLocation();
2448
2449 // Lex the left '('.
2450 Token Tok;
2451 PP.Lex(Tok);
2452 if (Tok.isNot(tok::l_paren)) {
2453 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
2454 return;
2455 }
2456
2457 // Lex the declaration reference(s).
2458 SmallVector<Token, 5> Identifiers;
2459 SourceLocation RParenLoc;
2460 bool LexID = true;
2461
2462 while (true) {
2463 PP.Lex(Tok);
2464
2465 if (LexID) {
2466 if (Tok.is(tok::identifier)) {
2467 Identifiers.push_back(Tok);
2468 LexID = false;
2469 continue;
2470 }
2471
2472 // Illegal token!
2473 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
2474 return;
2475 }
2476
2477 // We are execting a ')' or a ','.
2478 if (Tok.is(tok::comma)) {
2479 LexID = true;
2480 continue;
2481 }
2482
2483 if (Tok.is(tok::r_paren)) {
2484 RParenLoc = Tok.getLocation();
2485 break;
2486 }
2487
2488 // Illegal token!
2489 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
2490 return;
2491 }
2492
2493 PP.Lex(Tok);
2494 if (Tok.isNot(tok::eod)) {
2495 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2496 "unused";
2497 return;
2498 }
2499
2500 // Verify that we have a location for the right parenthesis.
2501 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
2502 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
2503
2504 // For each identifier token, insert into the token stream a
2505 // annot_pragma_unused token followed by the identifier token.
2506 // This allows us to cache a "#pragma unused" that occurs inside an inline
2507 // C++ member function.
2508
2510 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
2511 2 * Identifiers.size());
2512 for (unsigned i=0; i != Identifiers.size(); i++) {
2513 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
2514 pragmaUnusedTok.startToken();
2515 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
2516 pragmaUnusedTok.setLocation(UnusedLoc);
2517 idTok = Identifiers[i];
2518 }
2519 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2520 /*IsReinject=*/false);
2521}
2522
2523// #pragma weak identifier
2524// #pragma weak identifier '=' identifier
2525void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
2526 PragmaIntroducer Introducer,
2527 Token &WeakTok) {
2528 SourceLocation WeakLoc = WeakTok.getLocation();
2529
2530 Token Tok;
2531 PP.Lex(Tok);
2532 if (Tok.isNot(tok::identifier)) {
2533 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
2534 return;
2535 }
2536
2537 Token WeakName = Tok;
2538 bool HasAlias = false;
2539 Token AliasName;
2540
2541 PP.Lex(Tok);
2542 if (Tok.is(tok::equal)) {
2543 HasAlias = true;
2544 PP.Lex(Tok);
2545 if (Tok.isNot(tok::identifier)) {
2546 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2547 << "weak";
2548 return;
2549 }
2550 AliasName = Tok;
2551 PP.Lex(Tok);
2552 }
2553
2554 if (Tok.isNot(tok::eod)) {
2555 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2556 return;
2557 }
2558
2559 if (HasAlias) {
2561 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
2562 Token &pragmaUnusedTok = Toks[0];
2563 pragmaUnusedTok.startToken();
2564 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
2565 pragmaUnusedTok.setLocation(WeakLoc);
2566 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
2567 Toks[1] = WeakName;
2568 Toks[2] = AliasName;
2569 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2570 /*IsReinject=*/false);
2571 } else {
2573 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
2574 Token &pragmaUnusedTok = Toks[0];
2575 pragmaUnusedTok.startToken();
2576 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
2577 pragmaUnusedTok.setLocation(WeakLoc);
2578 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
2579 Toks[1] = WeakName;
2580 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2581 /*IsReinject=*/false);
2582 }
2583}
2584
2585// #pragma redefine_extname identifier identifier
2586void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
2587 PragmaIntroducer Introducer,
2588 Token &RedefToken) {
2589 SourceLocation RedefLoc = RedefToken.getLocation();
2590
2591 Token Tok;
2592 PP.Lex(Tok);
2593 if (Tok.isNot(tok::identifier)) {
2594 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2595 "redefine_extname";
2596 return;
2597 }
2598
2599 Token RedefName = Tok;
2600 PP.Lex(Tok);
2601
2602 if (Tok.isNot(tok::identifier)) {
2603 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2604 << "redefine_extname";
2605 return;
2606 }
2607
2608 Token AliasName = Tok;
2609 PP.Lex(Tok);
2610
2611 if (Tok.isNot(tok::eod)) {
2612 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2613 "redefine_extname";
2614 return;
2615 }
2616
2618 3);
2619 Token &pragmaRedefTok = Toks[0];
2620 pragmaRedefTok.startToken();
2621 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2622 pragmaRedefTok.setLocation(RedefLoc);
2623 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
2624 Toks[1] = RedefName;
2625 Toks[2] = AliasName;
2626 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2627 /*IsReinject=*/false);
2628}
2629
2630void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2631 PragmaIntroducer Introducer,
2632 Token &Tok) {
2633 tok::OnOffSwitch OOS;
2634 if (PP.LexOnOffSwitch(OOS))
2635 return;
2636
2638 1);
2639 Toks[0].startToken();
2640 Toks[0].setKind(tok::annot_pragma_fp_contract);
2641 Toks[0].setLocation(Tok.getLocation());
2642 Toks[0].setAnnotationEndLoc(Tok.getLocation());
2643 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2644 static_cast<uintptr_t>(OOS)));
2645 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2646 /*IsReinject=*/false);
2647}
2648
2649void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2650 PragmaIntroducer Introducer,
2651 Token &Tok) {
2653 if (Tok.isNot(tok::identifier)) {
2654 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2655 "OPENCL";
2656 return;
2657 }
2659 SourceLocation NameLoc = Tok.getLocation();
2660
2661 PP.Lex(Tok);
2662 if (Tok.isNot(tok::colon)) {
2663 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
2664 return;
2665 }
2666
2667 PP.Lex(Tok);
2668 if (Tok.isNot(tok::identifier)) {
2669 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
2670 return;
2671 }
2673
2674 OpenCLExtState State;
2675 if (Pred->isStr("enable")) {
2676 State = Enable;
2677 } else if (Pred->isStr("disable")) {
2678 State = Disable;
2679 } else if (Pred->isStr("begin"))
2680 State = Begin;
2681 else if (Pred->isStr("end"))
2682 State = End;
2683 else {
2684 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2685 << Ext->isStr("all");
2686 return;
2687 }
2688 SourceLocation StateLoc = Tok.getLocation();
2689
2690 PP.Lex(Tok);
2691 if (Tok.isNot(tok::eod)) {
2692 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2693 "OPENCL EXTENSION";
2694 return;
2695 }
2696
2697 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2698 Info->first = Ext;
2699 Info->second = State;
2701 1);
2702 Toks[0].startToken();
2703 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2704 Toks[0].setLocation(NameLoc);
2705 Toks[0].setAnnotationValue(static_cast<void*>(Info));
2706 Toks[0].setAnnotationEndLoc(StateLoc);
2707 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2708 /*IsReinject=*/false);
2709
2710 if (PP.getPPCallbacks())
2711 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2712 StateLoc, State);
2713}
2714
2715/// Handle '#pragma omp ...' when OpenMP is disabled and '#pragma acc ...' when
2716/// OpenACC is disabled.
2717template <diag::kind IgnoredDiag>
2718void PragmaNoSupportHandler<IgnoredDiag>::HandlePragma(
2719 Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) {
2720 if (!PP.getDiagnostics().isIgnored(IgnoredDiag, FirstTok.getLocation())) {
2721 PP.Diag(FirstTok, IgnoredDiag);
2723 SourceLocation());
2724 }
2726}
2727
2728/// Handle '#pragma omp ...' when OpenMP is enabled, and handle '#pragma acc...'
2729/// when OpenACC is enabled.
2730template <tok::TokenKind StartTok, tok::TokenKind EndTok,
2731 diag::kind UnexpectedDiag>
2732void PragmaSupportHandler<StartTok, EndTok, UnexpectedDiag>::HandlePragma(
2733 Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstTok) {
2735 Token Tok;
2736 Tok.startToken();
2737 Tok.setKind(StartTok);
2738 Tok.setLocation(Introducer.Loc);
2739
2740 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
2741 Pragma.push_back(Tok);
2742 PP.Lex(Tok);
2743 if (Tok.is(StartTok)) {
2744 PP.Diag(Tok, UnexpectedDiag) << 0;
2745 unsigned InnerPragmaCnt = 1;
2746 while (InnerPragmaCnt != 0) {
2747 PP.Lex(Tok);
2748 if (Tok.is(StartTok))
2749 ++InnerPragmaCnt;
2750 else if (Tok.is(EndTok))
2751 --InnerPragmaCnt;
2752 }
2753 PP.Lex(Tok);
2754 }
2755 }
2756 SourceLocation EodLoc = Tok.getLocation();
2757 Tok.startToken();
2758 Tok.setKind(EndTok);
2759 Tok.setLocation(EodLoc);
2760 Pragma.push_back(Tok);
2761
2762 auto Toks = std::make_unique<Token[]>(Pragma.size());
2763 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2764 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2765 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2766}
2767
2768/// Handle '#pragma pointers_to_members'
2769// The grammar for this pragma is as follows:
2770//
2771// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2772//
2773// #pragma pointers_to_members '(' 'best_case' ')'
2774// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2775// #pragma pointers_to_members '(' inheritance-model ')'
2776void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2777 PragmaIntroducer Introducer,
2778 Token &Tok) {
2779 SourceLocation PointersToMembersLoc = Tok.getLocation();
2780 PP.Lex(Tok);
2781 if (Tok.isNot(tok::l_paren)) {
2782 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2783 << "pointers_to_members";
2784 return;
2785 }
2786 PP.Lex(Tok);
2787 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2788 if (!Arg) {
2789 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2790 << "pointers_to_members";
2791 return;
2792 }
2793 PP.Lex(Tok);
2794
2795 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
2796 if (Arg->isStr("best_case")) {
2797 RepresentationMethod = LangOptions::PPTMK_BestCase;
2798 } else {
2799 if (Arg->isStr("full_generality")) {
2800 if (Tok.is(tok::comma)) {
2801 PP.Lex(Tok);
2802
2803 Arg = Tok.getIdentifierInfo();
2804 if (!Arg) {
2805 PP.Diag(Tok.getLocation(),
2806 diag::err_pragma_pointers_to_members_unknown_kind)
2807 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2808 return;
2809 }
2810 PP.Lex(Tok);
2811 } else if (Tok.is(tok::r_paren)) {
2812 // #pragma pointers_to_members(full_generality) implicitly specifies
2813 // virtual_inheritance.
2814 Arg = nullptr;
2816 } else {
2817 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2818 << "full_generality";
2819 return;
2820 }
2821 }
2822
2823 if (Arg) {
2824 if (Arg->isStr("single_inheritance")) {
2825 RepresentationMethod =
2827 } else if (Arg->isStr("multiple_inheritance")) {
2828 RepresentationMethod =
2830 } else if (Arg->isStr("virtual_inheritance")) {
2831 RepresentationMethod =
2833 } else {
2834 PP.Diag(Tok.getLocation(),
2835 diag::err_pragma_pointers_to_members_unknown_kind)
2836 << Arg << /*HasPointerDeclaration*/ 1;
2837 return;
2838 }
2839 }
2840 }
2841
2842 if (Tok.isNot(tok::r_paren)) {
2843 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2844 << (Arg ? Arg->getName() : "full_generality");
2845 return;
2846 }
2847
2848 SourceLocation EndLoc = Tok.getLocation();
2849 PP.Lex(Tok);
2850 if (Tok.isNot(tok::eod)) {
2851 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2852 << "pointers_to_members";
2853 return;
2854 }
2855
2856 Token AnnotTok;
2857 AnnotTok.startToken();
2858 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2859 AnnotTok.setLocation(PointersToMembersLoc);
2860 AnnotTok.setAnnotationEndLoc(EndLoc);
2861 AnnotTok.setAnnotationValue(
2862 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2863 PP.EnterToken(AnnotTok, /*IsReinject=*/true);
2864}
2865
2866/// Handle '#pragma vtordisp'
2867// The grammar for this pragma is as follows:
2868//
2869// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2870//
2871// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2872// #pragma vtordisp '(' 'pop' ')'
2873// #pragma vtordisp '(' ')'
2874void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2875 PragmaIntroducer Introducer, Token &Tok) {
2876 SourceLocation VtorDispLoc = Tok.getLocation();
2877 PP.Lex(Tok);
2878 if (Tok.isNot(tok::l_paren)) {
2879 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2880 return;
2881 }
2882 PP.Lex(Tok);
2883
2885 const IdentifierInfo *II = Tok.getIdentifierInfo();
2886 if (II) {
2887 if (II->isStr("push")) {
2888 // #pragma vtordisp(push, mode)
2889 PP.Lex(Tok);
2890 if (Tok.isNot(tok::comma)) {
2891 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2892 return;
2893 }
2894 PP.Lex(Tok);
2895 Action = Sema::PSK_Push_Set;
2896 // not push, could be on/off
2897 } else if (II->isStr("pop")) {
2898 // #pragma vtordisp(pop)
2899 PP.Lex(Tok);
2900 Action = Sema::PSK_Pop;
2901 }
2902 // not push or pop, could be on/off
2903 } else {
2904 if (Tok.is(tok::r_paren)) {
2905 // #pragma vtordisp()
2906 Action = Sema::PSK_Reset;
2907 }
2908 }
2909
2910
2911 uint64_t Value = 0;
2912 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
2913 const IdentifierInfo *II = Tok.getIdentifierInfo();
2914 if (II && II->isStr("off")) {
2915 PP.Lex(Tok);
2916 Value = 0;
2917 } else if (II && II->isStr("on")) {
2918 PP.Lex(Tok);
2919 Value = 1;
2920 } else if (Tok.is(tok::numeric_constant) &&
2922 if (Value > 2) {
2923 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2924 << 0 << 2 << "vtordisp";
2925 return;
2926 }
2927 } else {
2928 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2929 << "vtordisp";
2930 return;
2931 }
2932 }
2933
2934 // Finish the pragma: ')' $
2935 if (Tok.isNot(tok::r_paren)) {
2936 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2937 return;
2938 }
2939 SourceLocation EndLoc = Tok.getLocation();
2940 PP.Lex(Tok);
2941 if (Tok.isNot(tok::eod)) {
2942 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2943 << "vtordisp";
2944 return;
2945 }
2946
2947 // Enter the annotation.
2948 Token AnnotTok;
2949 AnnotTok.startToken();
2950 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2951 AnnotTok.setLocation(VtorDispLoc);
2952 AnnotTok.setAnnotationEndLoc(EndLoc);
2953 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
2954 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
2955 PP.EnterToken(AnnotTok, /*IsReinject=*/false);
2956}
2957
2958/// Handle all MS pragmas. Simply forwards the tokens after inserting
2959/// an annotation token.
2960void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2961 PragmaIntroducer Introducer, Token &Tok) {
2962 Token EoF, AnnotTok;
2963 EoF.startToken();
2964 EoF.setKind(tok::eof);
2965 AnnotTok.startToken();
2966 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2967 AnnotTok.setLocation(Tok.getLocation());
2969 SmallVector<Token, 8> TokenVector;
2970 // Suck up all of the tokens before the eod.
2971 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
2972 TokenVector.push_back(Tok);
2974 }
2975 // Add a sentinel EoF token to the end of the list.
2976 TokenVector.push_back(EoF);
2977 // We must allocate this array with new because EnterTokenStream is going to
2978 // delete it later.
2979 markAsReinjectedForRelexing(TokenVector);
2980 auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
2981 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
2982 auto Value = new (PP.getPreprocessorAllocator())
2983 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2984 TokenVector.size());
2985 AnnotTok.setAnnotationValue(Value);
2986 PP.EnterToken(AnnotTok, /*IsReinject*/ false);
2987}
2988
2989/// Handle the \#pragma float_control extension.
2990///
2991/// The syntax is:
2992/// \code
2993/// #pragma float_control(keyword[, setting] [,push])
2994/// \endcode
2995/// Where 'keyword' and 'setting' are identifiers.
2996// 'keyword' can be: precise, except, push, pop
2997// 'setting' can be: on, off
2998/// The optional arguments 'setting' and 'push' are supported only
2999/// when the keyword is 'precise' or 'except'.
3000void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
3001 PragmaIntroducer Introducer,
3002 Token &Tok) {
3004 SourceLocation FloatControlLoc = Tok.getLocation();
3005 Token PragmaName = Tok;
3006 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
3007 PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
3008 << PragmaName.getIdentifierInfo()->getName();
3009 return;
3010 }
3011 PP.Lex(Tok);
3012 if (Tok.isNot(tok::l_paren)) {
3013 PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
3014 return;
3015 }
3016
3017 // Read the identifier.
3018 PP.Lex(Tok);
3019 if (Tok.isNot(tok::identifier)) {
3020 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3021 return;
3022 }
3023
3024 // Verify that this is one of the float control options.
3027 llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
3028 .Case("precise", PFC_Precise)
3029 .Case("except", PFC_Except)
3030 .Case("push", PFC_Push)
3031 .Case("pop", PFC_Pop)
3032 .Default(PFC_Unknown);
3033 PP.Lex(Tok); // the identifier
3034 if (Kind == PFC_Unknown) {
3035 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3036 return;
3037 } else if (Kind == PFC_Push || Kind == PFC_Pop) {
3038 if (Tok.isNot(tok::r_paren)) {
3039 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3040 return;
3041 }
3042 PP.Lex(Tok); // Eat the r_paren
3043 Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;
3044 } else {
3045 if (Tok.is(tok::r_paren))
3046 // Selecting Precise or Except
3047 PP.Lex(Tok); // the r_paren
3048 else if (Tok.isNot(tok::comma)) {
3049 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3050 return;
3051 } else {
3052 PP.Lex(Tok); // ,
3053 if (!Tok.isAnyIdentifier()) {
3054 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3055 return;
3056 }
3057 StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
3058 if (PushOnOff == "on")
3059 // Kind is set correctly
3060 ;
3061 else if (PushOnOff == "off") {
3062 if (Kind == PFC_Precise)
3064 if (Kind == PFC_Except)
3066 } else if (PushOnOff == "push") {
3067 Action = Sema::PSK_Push_Set;
3068 } else {
3069 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3070 return;
3071 }
3072 PP.Lex(Tok); // the identifier
3073 if (Tok.is(tok::comma)) {
3074 PP.Lex(Tok); // ,
3075 if (!Tok.isAnyIdentifier()) {
3076 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3077 return;
3078 }
3079 StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
3080 if (ExpectedPush == "push") {
3081 Action = Sema::PSK_Push_Set;
3082 } else {
3083 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3084 return;
3085 }
3086 PP.Lex(Tok); // the push identifier
3087 }
3088 if (Tok.isNot(tok::r_paren)) {
3089 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
3090 return;
3091 }
3092 PP.Lex(Tok); // the r_paren
3093 }
3094 }
3095 SourceLocation EndLoc = Tok.getLocation();
3096 if (Tok.isNot(tok::eod)) {
3097 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3098 << "float_control";
3099 return;
3100 }
3101
3102 // Note: there is no accomodation for PP callback for this pragma.
3103
3104 // Enter the annotation.
3105 auto TokenArray = std::make_unique<Token[]>(1);
3106 TokenArray[0].startToken();
3107 TokenArray[0].setKind(tok::annot_pragma_float_control);
3108 TokenArray[0].setLocation(FloatControlLoc);
3109 TokenArray[0].setAnnotationEndLoc(EndLoc);
3110 // Create an encoding of Action and Value by shifting the Action into
3111 // the high 16 bits then union with the Kind.
3112 TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
3113 static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
3114 PP.EnterTokenStream(std::move(TokenArray), 1,
3115 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3116}
3117
3118/// Handle the Microsoft \#pragma detect_mismatch extension.
3119///
3120/// The syntax is:
3121/// \code
3122/// #pragma detect_mismatch("name", "value")
3123/// \endcode
3124/// Where 'name' and 'value' are quoted strings. The values are embedded in
3125/// the object file and passed along to the linker. If the linker detects a
3126/// mismatch in the object file's values for the given name, a LNK2038 error
3127/// is emitted. See MSDN for more details.
3128void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
3129 PragmaIntroducer Introducer,
3130 Token &Tok) {
3131 SourceLocation DetectMismatchLoc = Tok.getLocation();
3132 PP.Lex(Tok);
3133 if (Tok.isNot(tok::l_paren)) {
3134 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
3135 return;
3136 }
3137
3138 // Read the name to embed, which must be a string literal.
3139 std::string NameString;
3140 if (!PP.LexStringLiteral(Tok, NameString,
3141 "pragma detect_mismatch",
3142 /*AllowMacroExpansion=*/true))
3143 return;
3144
3145 // Read the comma followed by a second string literal.
3146 std::string ValueString;
3147 if (Tok.isNot(tok::comma)) {
3148 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
3149 return;
3150 }
3151
3152 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
3153 /*AllowMacroExpansion=*/true))
3154 return;
3155
3156 if (Tok.isNot(tok::r_paren)) {
3157 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3158 return;
3159 }
3160 PP.Lex(Tok); // Eat the r_paren.
3161
3162 if (Tok.isNot(tok::eod)) {
3163 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
3164 return;
3165 }
3166
3167 // If the pragma is lexically sound, notify any interested PPCallbacks.
3168 if (PP.getPPCallbacks())
3169 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
3170 ValueString);
3171
3172 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
3173}
3174
3175/// Handle the microsoft \#pragma comment extension.
3176///
3177/// The syntax is:
3178/// \code
3179/// #pragma comment(linker, "foo")
3180/// \endcode
3181/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
3182/// "foo" is a string, which is fully macro expanded, and permits string
3183/// concatenation, embedded escape characters etc. See MSDN for more details.
3184void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
3185 PragmaIntroducer Introducer,
3186 Token &Tok) {
3187 SourceLocation CommentLoc = Tok.getLocation();
3188 PP.Lex(Tok);
3189 if (Tok.isNot(tok::l_paren)) {
3190 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
3191 return;
3192 }
3193
3194 // Read the identifier.
3195 PP.Lex(Tok);
3196 if (Tok.isNot(tok::identifier)) {
3197 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
3198 return;
3199 }
3200
3201 // Verify that this is one of the 5 explicitly listed options.
3204 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
3205 .Case("linker", PCK_Linker)
3206 .Case("lib", PCK_Lib)
3207 .Case("compiler", PCK_Compiler)
3208 .Case("exestr", PCK_ExeStr)
3209 .Case("user", PCK_User)
3210 .Default(PCK_Unknown);
3211 if (Kind == PCK_Unknown) {
3212 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
3213 return;
3214 }
3215
3216 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
3217 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
3218 << II->getName();
3219 return;
3220 }
3221
3222 // Read the optional string if present.
3223 PP.Lex(Tok);
3224 std::string ArgumentString;
3225 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
3226 "pragma comment",
3227 /*AllowMacroExpansion=*/true))
3228 return;
3229
3230 // FIXME: warn that 'exestr' is deprecated.
3231 // FIXME: If the kind is "compiler" warn if the string is present (it is
3232 // ignored).
3233 // The MSDN docs say that "lib" and "linker" require a string and have a short
3234 // list of linker options they support, but in practice MSVC doesn't
3235 // issue a diagnostic. Therefore neither does clang.
3236
3237 if (Tok.isNot(tok::r_paren)) {
3238 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3239 return;
3240 }
3241 PP.Lex(Tok); // eat the r_paren.
3242
3243 if (Tok.isNot(tok::eod)) {
3244 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3245 return;
3246 }
3247
3248 // If the pragma is lexically sound, notify any interested PPCallbacks.
3249 if (PP.getPPCallbacks())
3250 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
3251
3252 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
3253}
3254
3255// #pragma clang optimize off
3256// #pragma clang optimize on
3257void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
3258 PragmaIntroducer Introducer,
3259 Token &FirstToken) {
3260 Token Tok;
3261 PP.Lex(Tok);
3262 if (Tok.is(tok::eod)) {
3263 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3264 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
3265 return;
3266 }
3267 if (Tok.isNot(tok::identifier)) {
3268 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3269 << PP.getSpelling(Tok);
3270 return;
3271 }
3272 const IdentifierInfo *II = Tok.getIdentifierInfo();
3273 // The only accepted values are 'on' or 'off'.
3274 bool IsOn = false;
3275 if (II->isStr("on")) {
3276 IsOn = true;
3277 } else if (!II->isStr("off")) {
3278 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3279 << PP.getSpelling(Tok);
3280 return;
3281 }
3282 PP.Lex(Tok);
3283
3284 if (Tok.isNot(tok::eod)) {
3285 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
3286 << PP.getSpelling(Tok);
3287 return;
3288 }
3289
3290 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
3291}
3292
3293namespace {
3294/// Used as the annotation value for tok::annot_pragma_fp.
3295struct TokFPAnnotValue {
3296 enum FlagValues { On, Off, Fast };
3297
3298 std::optional<LangOptions::FPModeKind> ContractValue;
3299 std::optional<LangOptions::FPModeKind> ReassociateValue;
3300 std::optional<LangOptions::FPModeKind> ReciprocalValue;
3301 std::optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
3302 std::optional<LangOptions::FPEvalMethodKind> EvalMethodValue;
3303};
3304} // end anonymous namespace
3305
3306void PragmaFPHandler::HandlePragma(Preprocessor &PP,
3307 PragmaIntroducer Introducer, Token &Tok) {
3308 // fp
3309 Token PragmaName = Tok;
3310 SmallVector<Token, 1> TokenList;
3311
3312 PP.Lex(Tok);
3313 if (Tok.isNot(tok::identifier)) {
3314 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3315 << /*MissingOption=*/true << "";
3316 return;
3317 }
3318
3319 auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;
3320 while (Tok.is(tok::identifier)) {
3321 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3322
3323 auto FlagKind =
3324 llvm::StringSwitch<std::optional<PragmaFPKind>>(OptionInfo->getName())
3325 .Case("contract", PFK_Contract)
3326 .Case("reassociate", PFK_Reassociate)
3327 .Case("exceptions", PFK_Exceptions)
3328 .Case("eval_method", PFK_EvalMethod)
3329 .Case("reciprocal", PFK_Reciprocal)
3330 .Default(std::nullopt);
3331 if (!FlagKind) {
3332 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3333 << /*MissingOption=*/false << OptionInfo;
3334 return;
3335 }
3336 PP.Lex(Tok);
3337
3338 // Read '('
3339 if (Tok.isNot(tok::l_paren)) {
3340 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3341 return;
3342 }
3343 PP.Lex(Tok);
3344 bool isEvalMethodDouble =
3345 Tok.is(tok::kw_double) && FlagKind == PFK_EvalMethod;
3346
3347 // Don't diagnose if we have an eval_metod pragma with "double" kind.
3348 if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) {
3349 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3350 << PP.getSpelling(Tok) << OptionInfo->getName()
3351 << static_cast<int>(*FlagKind);
3352 return;
3353 }
3354 const IdentifierInfo *II = Tok.getIdentifierInfo();
3355
3356 if (FlagKind == PFK_Contract) {
3357 AnnotValue->ContractValue =
3358 llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
3359 II->getName())
3363 .Default(std::nullopt);
3364 if (!AnnotValue->ContractValue) {
3365 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3366 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3367 return;
3368 }
3369 } else if (FlagKind == PFK_Reassociate || FlagKind == PFK_Reciprocal) {
3370 auto &Value = FlagKind == PFK_Reassociate ? AnnotValue->ReassociateValue
3371 : AnnotValue->ReciprocalValue;
3372 Value = llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
3373 II->getName())
3376 .Default(std::nullopt);
3377 if (!Value) {
3378 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3379 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3380 return;
3381 }
3382 } else if (FlagKind == PFK_Exceptions) {
3383 AnnotValue->ExceptionsValue =
3384 llvm::StringSwitch<std::optional<LangOptions::FPExceptionModeKind>>(
3385 II->getName())
3386 .Case("ignore", LangOptions::FPE_Ignore)
3387 .Case("maytrap", LangOptions::FPE_MayTrap)
3388 .Case("strict", LangOptions::FPE_Strict)
3389 .Default(std::nullopt);
3390 if (!AnnotValue->ExceptionsValue) {
3391 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3392 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3393 return;
3394 }
3395 } else if (FlagKind == PFK_EvalMethod) {
3396 AnnotValue->EvalMethodValue =
3397 llvm::StringSwitch<std::optional<LangOptions::FPEvalMethodKind>>(
3398 II->getName())
3402 .Default(std::nullopt);
3403 if (!AnnotValue->EvalMethodValue) {
3404 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3405 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3406 return;
3407 }
3408 }
3409 PP.Lex(Tok);
3410
3411 // Read ')'
3412 if (Tok.isNot(tok::r_paren)) {
3413 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3414 return;
3415 }
3416 PP.Lex(Tok);
3417 }
3418
3419 if (Tok.isNot(tok::eod)) {
3420 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3421 << "clang fp";
3422 return;
3423 }
3424
3425 Token FPTok;
3426 FPTok.startToken();
3427 FPTok.setKind(tok::annot_pragma_fp);
3428 FPTok.setLocation(PragmaName.getLocation());
3429 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
3430 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
3431 TokenList.push_back(FPTok);
3432
3433 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3434 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3435
3436 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3437 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3438}
3439
3440void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
3441 PragmaIntroducer Introducer,
3442 Token &Tok) {
3443 Token PragmaName = Tok;
3444 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
3445 PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
3446 << PragmaName.getIdentifierInfo()->getName();
3447 return;
3448 }
3449
3450 PP.Lex(Tok);
3451 if (Tok.isNot(tok::identifier)) {
3452 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
3453 << PragmaName.getIdentifierInfo()->getName();
3454 return;
3455 }
3457
3458 auto RM =
3459 llvm::StringSwitch<llvm::RoundingMode>(II->getName())
3460 .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)
3461 .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)
3462 .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)
3463 .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)
3464 .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)
3465 .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)
3466 .Default(llvm::RoundingMode::Invalid);
3467 if (RM == llvm::RoundingMode::Invalid) {
3468 PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);
3469 return;
3470 }
3471 PP.Lex(Tok);
3472
3473 if (Tok.isNot(tok::eod)) {
3474 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3475 << "STDC FENV_ROUND";
3476 return;
3477 }
3478
3479 // Until the pragma is fully implemented, issue a warning.
3480 PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
3481
3483 1);
3484 Toks[0].startToken();
3485 Toks[0].setKind(tok::annot_pragma_fenv_round);
3486 Toks[0].setLocation(Tok.getLocation());
3487 Toks[0].setAnnotationEndLoc(Tok.getLocation());
3488 Toks[0].setAnnotationValue(
3489 reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));
3490 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
3491 /*IsReinject=*/false);
3492}
3493
3494void Parser::HandlePragmaFP() {
3495 assert(Tok.is(tok::annot_pragma_fp));
3496 auto *AnnotValue =
3497 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
3498
3499 if (AnnotValue->ReassociateValue)
3500 Actions.ActOnPragmaFPValueChangingOption(
3501 Tok.getLocation(), PFK_Reassociate,
3502 *AnnotValue->ReassociateValue == LangOptions::FPModeKind::FPM_On);
3503
3504 if (AnnotValue->ReciprocalValue)
3505 Actions.ActOnPragmaFPValueChangingOption(
3506 Tok.getLocation(), PFK_Reciprocal,
3507 *AnnotValue->ReciprocalValue == LangOptions::FPModeKind::FPM_On);
3508
3509 if (AnnotValue->ContractValue)
3510 Actions.ActOnPragmaFPContract(Tok.getLocation(),
3511 *AnnotValue->ContractValue);
3512 if (AnnotValue->ExceptionsValue)
3513 Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
3514 *AnnotValue->ExceptionsValue);
3515 if (AnnotValue->EvalMethodValue)
3516 Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(),
3517 *AnnotValue->EvalMethodValue);
3518 ConsumeAnnotationToken();
3519}
3520
3521/// Parses loop or unroll pragma hint value and fills in Info.
3522static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
3523 Token Option, bool ValueInParens,
3524 PragmaLoopHintInfo &Info) {
3526 int OpenParens = ValueInParens ? 1 : 0;
3527 // Read constant expression.
3528 while (Tok.isNot(tok::eod)) {
3529 if (Tok.is(tok::l_paren))
3530 OpenParens++;
3531 else if (Tok.is(tok::r_paren)) {
3532 OpenParens--;
3533 if (OpenParens == 0 && ValueInParens)
3534 break;
3535 }
3536
3537 ValueList.push_back(Tok);
3538 PP.Lex(Tok);
3539 }
3540
3541 if (ValueInParens) {
3542 // Read ')'
3543 if (Tok.isNot(tok::r_paren)) {
3544 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3545 return true;
3546 }
3547 PP.Lex(Tok);
3548 }
3549
3550 Token EOFTok;
3551 EOFTok.startToken();
3552 EOFTok.setKind(tok::eof);
3553 EOFTok.setLocation(Tok.getLocation());
3554 ValueList.push_back(EOFTok); // Terminates expression for parsing.
3555
3556 markAsReinjectedForRelexing(ValueList);
3558
3559 Info.PragmaName = PragmaName;
3560 Info.Option = Option;
3561 return false;
3562}
3563
3564/// Handle the \#pragma clang loop directive.
3565/// #pragma clang 'loop' loop-hints
3566///
3567/// loop-hints:
3568/// loop-hint loop-hints[opt]
3569///
3570/// loop-hint:
3571/// 'vectorize' '(' loop-hint-keyword ')'
3572/// 'interleave' '(' loop-hint-keyword ')'
3573/// 'unroll' '(' unroll-hint-keyword ')'
3574/// 'vectorize_predicate' '(' loop-hint-keyword ')'
3575/// 'vectorize_width' '(' loop-hint-value ')'
3576/// 'interleave_count' '(' loop-hint-value ')'
3577/// 'unroll_count' '(' loop-hint-value ')'
3578/// 'pipeline' '(' disable ')'
3579/// 'pipeline_initiation_interval' '(' loop-hint-value ')'
3580///
3581/// loop-hint-keyword:
3582/// 'enable'
3583/// 'disable'
3584/// 'assume_safety'
3585///
3586/// unroll-hint-keyword:
3587/// 'enable'
3588/// 'disable'
3589/// 'full'
3590///
3591/// loop-hint-value:
3592/// constant-expression
3593///
3594/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
3595/// try vectorizing the instructions of the loop it precedes. Specifying
3596/// interleave(enable) or interleave_count(_value_) instructs llvm to try
3597/// interleaving multiple iterations of the loop it precedes. The width of the
3598/// vector instructions is specified by vectorize_width() and the number of
3599/// interleaved loop iterations is specified by interleave_count(). Specifying a
3600/// value of 1 effectively disables vectorization/interleaving, even if it is
3601/// possible and profitable, and 0 is invalid. The loop vectorizer currently
3602/// only works on inner loops.
3603///
3604/// The unroll and unroll_count directives control the concatenation
3605/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
3606/// completely if the trip count is known at compile time and unroll partially
3607/// if the trip count is not known. Specifying unroll(full) is similar to
3608/// unroll(enable) but will unroll the loop only if the trip count is known at
3609/// compile time. Specifying unroll(disable) disables unrolling for the
3610/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
3611/// loop the number of times indicated by the value.
3612void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
3613 PragmaIntroducer Introducer,
3614 Token &Tok) {
3615 // Incoming token is "loop" from "#pragma clang loop".
3616 Token PragmaName = Tok;
3617 SmallVector<Token, 1> TokenList;
3618
3619 // Lex the optimization option and verify it is an identifier.
3620 PP.Lex(Tok);
3621 if (Tok.isNot(tok::identifier)) {
3622 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3623 << /*MissingOption=*/true << "";
3624 return;
3625 }
3626
3627 while (Tok.is(tok::identifier)) {
3628 Token Option = Tok;
3629 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3630
3631 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
3632 .Case("vectorize", true)
3633 .Case("interleave", true)
3634 .Case("unroll", true)
3635 .Case("distribute", true)
3636 .Case("vectorize_predicate", true)
3637 .Case("vectorize_width", true)
3638 .Case("interleave_count", true)
3639 .Case("unroll_count", true)
3640 .Case("pipeline", true)
3641 .Case("pipeline_initiation_interval", true)
3642 .Default(false);
3643 if (!OptionValid) {
3644 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3645 << /*MissingOption=*/false << OptionInfo;
3646 return;
3647 }
3648 PP.Lex(Tok);
3649
3650 // Read '('
3651 if (Tok.isNot(tok::l_paren)) {
3652 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3653 return;
3654 }
3655 PP.Lex(Tok);
3656
3657 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3658 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
3659 *Info))
3660 return;
3661
3662 // Generate the loop hint token.
3663 Token LoopHintTok;
3664 LoopHintTok.startToken();
3665 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
3666 LoopHintTok.setLocation(Introducer.Loc);
3667 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
3668 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
3669 TokenList.push_back(LoopHintTok);
3670 }
3671
3672 if (Tok.isNot(tok::eod)) {
3673 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3674 << "clang loop";
3675 return;
3676 }
3677
3678 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3679 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3680
3681 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3682 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3683}
3684
3685/// Handle the loop unroll optimization pragmas.
3686/// #pragma unroll
3687/// #pragma unroll unroll-hint-value
3688/// #pragma unroll '(' unroll-hint-value ')'
3689/// #pragma nounroll
3690/// #pragma unroll_and_jam
3691/// #pragma unroll_and_jam unroll-hint-value
3692/// #pragma unroll_and_jam '(' unroll-hint-value ')'
3693/// #pragma nounroll_and_jam
3694///
3695/// unroll-hint-value:
3696/// constant-expression
3697///
3698/// Loop unrolling hints can be specified with '#pragma unroll' or
3699/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
3700/// contained in parentheses. With no argument the directive instructs llvm to
3701/// try to unroll the loop completely. A positive integer argument can be
3702/// specified to indicate the number of times the loop should be unrolled. To
3703/// maximize compatibility with other compilers the unroll count argument can be
3704/// specified with or without parentheses. Specifying, '#pragma nounroll'
3705/// disables unrolling of the loop.
3706void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
3707 PragmaIntroducer Introducer,
3708 Token &Tok) {
3709 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
3710 // "#pragma nounroll".
3711 Token PragmaName = Tok;
3712 PP.Lex(Tok);
3713 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3714 if (Tok.is(tok::eod)) {
3715 // nounroll or unroll pragma without an argument.
3716 Info->PragmaName = PragmaName;
3717 Info->Option.startToken();
3718 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
3719 PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
3720 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3721 << PragmaName.getIdentifierInfo()->getName();
3722 return;
3723 } else {
3724 // Unroll pragma with an argument: "#pragma unroll N" or
3725 // "#pragma unroll(N)".
3726 // Read '(' if it exists.
3727 bool ValueInParens = Tok.is(tok::l_paren);
3728 if (ValueInParens)
3729 PP.Lex(Tok);
3730
3731 Token Option;
3732 Option.startToken();
3733 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
3734 return;
3735
3736 // In CUDA, the argument to '#pragma unroll' should not be contained in
3737 // parentheses.
3738 if (PP.getLangOpts().CUDA && ValueInParens)
3739 PP.Diag(Info->Toks[0].getLocation(),
3740 diag::warn_pragma_unroll_cuda_value_in_parens);
3741
3742 if (Tok.isNot(tok::eod)) {
3743 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3744 << "unroll";
3745 return;
3746 }
3747 }
3748
3749 // Generate the hint token.
3750 auto TokenArray = std::make_unique<Token[]>(1);
3751 TokenArray[0].startToken();
3752 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
3753 TokenArray[0].setLocation(Introducer.Loc);
3754 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
3755 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3756 PP.EnterTokenStream(std::move(TokenArray), 1,
3757 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3758}
3759
3760bool Parser::HandlePragmaMSFunction(StringRef PragmaName,
3761 SourceLocation PragmaLocation) {
3762 Token FirstTok = Tok;
3763
3764 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3765 PragmaName))
3766 return false;
3767
3768 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3769
3770 llvm::SmallVector<StringRef> NoBuiltins;
3771 while (Tok.is(tok::identifier)) {
3772 IdentifierInfo *II = Tok.getIdentifierInfo();
3773 if (!II->getBuiltinID())
3774 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3775 << II << SuggestIntrinH;
3776 else
3777 NoBuiltins.emplace_back(II->getName());
3778
3779 PP.Lex(Tok);
3780 if (Tok.isNot(tok::comma))
3781 break;
3782 PP.Lex(Tok); // ,
3783 }
3784
3785 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3786 PragmaName) ||
3787 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3788 PragmaName))
3789 return false;
3790
3791 Actions.ActOnPragmaMSFunction(FirstTok.getLocation(), NoBuiltins);
3792 return true;
3793}
3794
3795bool Parser::HandlePragmaMSOptimize(StringRef PragmaName,
3796 SourceLocation PragmaLocation) {
3797 Token FirstTok = Tok;
3798 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3799 PragmaName))
3800 return false;
3801
3802 if (Tok.isNot(tok::string_literal)) {
3803 PP.Diag(PragmaLocation, diag::warn_pragma_expected_string) << PragmaName;
3804 return false;
3805 }
3807 if (StringResult.isInvalid())
3808 return false; // Already diagnosed.
3809 StringLiteral *OptimizationList = cast<StringLiteral>(StringResult.get());
3810 if (OptimizationList->getCharByteWidth() != 1) {
3811 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
3812 << PragmaName;
3813 return false;
3814 }
3815
3816 if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
3817 PragmaName))
3818 return false;
3819
3820 if (Tok.is(tok::eof) || Tok.is(tok::r_paren)) {
3821 PP.Diag(PragmaLocation, diag::warn_pragma_missing_argument)
3822 << PragmaName << /*Expected=*/true << "'on' or 'off'";
3823 return false;
3824 }
3825 IdentifierInfo *II = Tok.getIdentifierInfo();
3826 if (!II || (!II->isStr("on") && !II->isStr("off"))) {
3827 PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3828 << PP.getSpelling(Tok) << PragmaName << /*Expected=*/true
3829 << "'on' or 'off'";
3830 return false;
3831 }
3832 bool IsOn = II->isStr("on");
3833 PP.Lex(Tok);
3834
3835 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3836 PragmaName))
3837 return false;
3838
3839 // TODO: Add support for "sgty"
3840 if (!OptimizationList->getString().empty()) {
3841 PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3842 << OptimizationList->getString() << PragmaName << /*Expected=*/true
3843 << "\"\"";
3844 return false;
3845 }
3846
3847 if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3848 PragmaName))
3849 return false;
3850
3851 Actions.ActOnPragmaMSOptimize(FirstTok.getLocation(), IsOn);
3852 return true;
3853}
3854
3855/// Handle the Microsoft \#pragma intrinsic extension.
3856///
3857/// The syntax is:
3858/// \code
3859/// #pragma intrinsic(memset)
3860/// #pragma intrinsic(strlen, memcpy)
3861/// \endcode
3862///
3863/// Pragma intrisic tells the compiler to use a builtin version of the
3864/// function. Clang does it anyway, so the pragma doesn't really do anything.
3865/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3866/// isn't an intrinsic in clang and suggest to include intrin.h, as well as
3867/// declare the builtin if it has not been declared.
3868bool Parser::HandlePragmaMSIntrinsic(StringRef PragmaName,
3869 SourceLocation PragmaLocation) {
3870 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3871 PragmaName))
3872 return false;
3873
3874 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3875
3876 while (Tok.is(tok::identifier)) {
3877 IdentifierInfo *II = Tok.getIdentifierInfo();
3878 if (!II->getBuiltinID())
3879 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3880 << II << SuggestIntrinH;
3881 // If the builtin hasn't already been declared, declare it now.
3882 DeclarationNameInfo NameInfo(II, Tok.getLocation());
3883 LookupResult Previous(Actions, NameInfo, Sema::LookupOrdinaryName,
3885 Actions.LookupName(Previous, Actions.getCurScope(),
3886 /*CreateBuiltins*/ false);
3887 if (Previous.empty())
3888 Actions.LazilyCreateBuiltin(II, II->getBuiltinID(), Actions.getCurScope(),
3889 /*ForRedeclaration*/ true, Tok.getLocation());
3890 PP.Lex(Tok);
3891 if (Tok.isNot(tok::comma))
3892 break;
3893 PP.Lex(Tok);
3894 }
3895 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3896 PragmaName))
3897 return false;
3898
3899 if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3900 PragmaName))
3901 return false;
3902 return true;
3903}
3904
3905void PragmaForceCUDAHostDeviceHandler::HandlePragma(
3906 Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
3907 Token FirstTok = Tok;
3908
3909 PP.Lex(Tok);
3911 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
3912 PP.Diag(FirstTok.getLocation(),
3913 diag::warn_pragma_force_cuda_host_device_bad_arg);
3914 return;
3915 }
3916
3917 if (Info->isStr("begin"))
3918 Actions.CUDA().PushForceHostDevice();
3919 else if (!Actions.CUDA().PopForceHostDevice())
3920 PP.Diag(FirstTok.getLocation(),
3921 diag::err_pragma_cannot_end_force_cuda_host_device);
3922
3923 PP.Lex(Tok);
3924 if (!Tok.is(tok::eod))
3925 PP.Diag(FirstTok.getLocation(),
3926 diag::warn_pragma_force_cuda_host_device_bad_arg);
3927}
3928
3929/// Handle the #pragma clang attribute directive.
3930///
3931/// The syntax is:
3932/// \code
3933/// #pragma clang attribute push (attribute, subject-set)
3934/// #pragma clang attribute push
3935/// #pragma clang attribute (attribute, subject-set)
3936/// #pragma clang attribute pop
3937/// \endcode
3938///
3939/// There are also 'namespace' variants of push and pop directives. The bare
3940/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3941/// namespace, since it always applies attributes to the most recently pushed
3942/// group, regardless of namespace.
3943/// \code
3944/// #pragma clang attribute namespace.push (attribute, subject-set)
3945/// #pragma clang attribute namespace.push
3946/// #pragma clang attribute namespace.pop
3947/// \endcode
3948///
3949/// The subject-set clause defines the set of declarations which receive the
3950/// attribute. Its exact syntax is described in the LanguageExtensions document
3951/// in Clang's documentation.
3952///
3953/// This directive instructs the compiler to begin/finish applying the specified
3954/// attribute to the set of attribute-specific declarations in the active range
3955/// of the pragma.
3956void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
3957 PragmaIntroducer Introducer,
3958 Token &FirstToken) {
3959 Token Tok;
3960 PP.Lex(Tok);
3961 auto *Info = new (PP.getPreprocessorAllocator())
3962 PragmaAttributeInfo(AttributesForPragmaAttribute);
3963
3964 // Parse the optional namespace followed by a period.
3965 if (Tok.is(tok::identifier)) {
3967 if (!II->isStr("push") && !II->isStr("pop")) {
3968 Info->Namespace = II;
3969 PP.Lex(Tok);
3970
3971 if (!Tok.is(tok::period)) {
3972 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
3973 << II;
3974 return;
3975 }
3976 PP.Lex(Tok);
3977 }
3978 }
3979
3980 if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
3981 PP.Diag(Tok.getLocation(),
3982 diag::err_pragma_attribute_expected_push_pop_paren);
3983 return;
3984 }
3985
3986 // Determine what action this pragma clang attribute represents.
3987 if (Tok.is(tok::l_paren)) {
3988 if (Info->Namespace) {
3989 PP.Diag(Tok.getLocation(),
3990 diag::err_pragma_attribute_namespace_on_attribute);
3991 PP.Diag(Tok.getLocation(),
3992 diag::note_pragma_attribute_namespace_on_attribute);
3993 return;
3994 }
3995 Info->Action = PragmaAttributeInfo::Attribute;
3996 } else {
3997 const IdentifierInfo *II = Tok.getIdentifierInfo();
3998 if (II->isStr("push"))
3999 Info->Action = PragmaAttributeInfo::Push;
4000 else if (II->isStr("pop"))
4001 Info->Action = PragmaAttributeInfo::Pop;
4002 else {
4003 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
4004 << PP.getSpelling(Tok);
4005 return;
4006 }
4007
4008 PP.Lex(Tok);
4009 }
4010
4011 // Parse the actual attribute.
4012 if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
4013 Info->Action == PragmaAttributeInfo::Attribute) {
4014 if (Tok.isNot(tok::l_paren)) {
4015 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
4016 return;
4017 }
4018 PP.Lex(Tok);
4019
4020 // Lex the attribute tokens.
4021 SmallVector<Token, 16> AttributeTokens;
4022 int OpenParens = 1;
4023 while (Tok.isNot(tok::eod)) {
4024 if (Tok.is(tok::l_paren))
4025 OpenParens++;
4026 else if (Tok.is(tok::r_paren)) {
4027 OpenParens--;
4028 if (OpenParens == 0)
4029 break;
4030 }
4031
4032 AttributeTokens.push_back(Tok);
4033 PP.Lex(Tok);
4034 }
4035
4036 if (AttributeTokens.empty()) {
4037 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
4038 return;
4039 }
4040 if (Tok.isNot(tok::r_paren)) {
4041 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
4042 return;
4043 }
4044 SourceLocation EndLoc = Tok.getLocation();
4045 PP.Lex(Tok);
4046
4047 // Terminate the attribute for parsing.
4048 Token EOFTok;
4049 EOFTok.startToken();
4050 EOFTok.setKind(tok::eof);
4051 EOFTok.setLocation(EndLoc);
4052 AttributeTokens.push_back(EOFTok);
4053
4054 markAsReinjectedForRelexing(AttributeTokens);
4055 Info->Tokens =
4056 llvm::ArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
4057 }
4058
4059 if (Tok.isNot(tok::eod))
4060 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4061 << "clang attribute";
4062
4063 // Generate the annotated pragma token.
4064 auto TokenArray = std::make_unique<Token[]>(1);
4065 TokenArray[0].startToken();
4066 TokenArray[0].setKind(tok::annot_pragma_attribute);
4067 TokenArray[0].setLocation(FirstToken.getLocation());
4068 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
4069 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
4070 PP.EnterTokenStream(std::move(TokenArray), 1,
4071 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
4072}
4073
4074// Handle '#pragma clang max_tokens 12345'.
4075void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
4076 PragmaIntroducer Introducer,
4077 Token &Tok) {
4078 PP.Lex(Tok);
4079 if (Tok.is(tok::eod)) {
4080 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
4081 << "clang max_tokens_here" << /*Expected=*/true << "integer";
4082 return;
4083 }
4084
4086 uint64_t MaxTokens;
4087 if (Tok.isNot(tok::numeric_constant) ||
4088 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
4089 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
4090 << "clang max_tokens_here";
4091 return;
4092 }
4093
4094 if (Tok.isNot(tok::eod)) {
4095 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4096 << "clang max_tokens_here";
4097 return;
4098 }
4099
4100 if (PP.getTokenCount() > MaxTokens) {
4101 PP.Diag(Loc, diag::warn_max_tokens)
4102 << PP.getTokenCount() << (unsigned)MaxTokens;
4103 }
4104}
4105
4106// Handle '#pragma clang max_tokens_total 12345'.
4107void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
4108 PragmaIntroducer Introducer,
4109 Token &Tok) {
4110 PP.Lex(Tok);
4111 if (Tok.is(tok::eod)) {
4112 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
4113 << "clang max_tokens_total" << /*Expected=*/true << "integer";
4114 return;
4115 }
4116
4118 uint64_t MaxTokens;
4119 if (Tok.isNot(tok::numeric_constant) ||
4120 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
4121 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
4122 << "clang max_tokens_total";
4123 return;
4124 }
4125
4126 if (Tok.isNot(tok::eod)) {
4127 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4128 << "clang max_tokens_total";
4129 return;
4130 }
4131
4132 PP.overrideMaxTokens(MaxTokens, Loc);
4133}
4134
4135// Handle '#pragma clang riscv intrinsic vector'.
4136// '#pragma clang riscv intrinsic sifive_vector'.
4137// '#pragma clang riscv intrinsic andes_vector'.
4138void PragmaRISCVHandler::HandlePragma(Preprocessor &PP,
4139 PragmaIntroducer Introducer,
4140 Token &FirstToken) {
4141 Token Tok;
4142 PP.Lex(Tok);
4144
4145 if (!II || !II->isStr("intrinsic")) {
4146 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
4147 << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'";
4148 return;
4149 }
4150
4151 PP.Lex(Tok);
4152 II = Tok.getIdentifierInfo();
4153 if (!II || !(II->isStr("vector") || II->isStr("sifive_vector") ||
4154 II->isStr("andes_vector"))) {
4155 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
4156 << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true
4157 << "'vector', 'sifive_vector' or 'andes_vector'";
4158 return;
4159 }
4160
4161 PP.Lex(Tok);
4162 if (Tok.isNot(tok::eod)) {
4163 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4164 << "clang riscv intrinsic";
4165 return;
4166 }
4167
4168 if (II->isStr("vector"))
4169 Actions.RISCV().DeclareRVVBuiltins = true;
4170 else if (II->isStr("sifive_vector"))
4171 Actions.RISCV().DeclareSiFiveVectorBuiltins = true;
4172 else if (II->isStr("andes_vector"))
4173 Actions.RISCV().DeclareAndesVectorBuiltins = true;
4174}
Defines the clang::ASTContext interface.
Token Tok
The Token.
FormatToken * Previous
The previous token in the unwrapped line.
bool is(tok::TokenKind Kind) const
static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, bool IsOptions)
static void diagnoseUnknownAttributeSubjectSubRule(Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName, StringRef SubRuleName, SourceLocation SubRuleLoc)
static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, Token Option, bool ValueInParens, PragmaLoopHintInfo &Info)
Parses loop or unroll pragma hint value and fills in Info.
static void diagnoseExpectedAttributeSubjectSubRule(Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName, SourceLocation SubRuleLoc)
static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule)
static StringRef getIdentifier(const Token &Tok)
static std::string PragmaLoopHintString(Token PragmaName, Token Option)
Defines the clang::Preprocessor interface.
ArrayRef< SVal > ValueList
@ NotForRedeclaration
The lookup is a reference to this name that is not for the purpose of redeclaring the name.
This file declares semantic analysis for CUDA constructs.
This file declares facilities that support code completion.
This file declares semantic analysis functions specific to RISC-V.
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
bool isUsable() const
Definition Ownership.h:169
static CharSourceRange getCharRange(SourceRange R)
A little helper class used to produce diagnostics.
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine a...
void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc)
This allows the client to specify that certain warnings are ignored.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
Definition Diagnostic.h:950
EmptyPragmaHandler - A pragma handler which takes no action, which can be used to ignore particular p...
Definition Pragma.h:84
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:194
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Definition Expr.h:246
ExprDependence getDependence() const
Definition Expr.h:164
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Definition Diagnostic.h:139
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
Definition Diagnostic.h:128
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
Definition Diagnostic.h:102
One of these records is kept for each identifier that is lexed.
unsigned getBuiltinID() const
Return a value indicating whether this is a builtin function.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
StringRef getName() const
Return the actual identifier string.
@ FEM_Extended
Use extended type for fp arithmetic.
@ FEM_Double
Use the type double for fp arithmetic.
@ FEM_Source
Use the declared type for fp arithmetic.
ComplexRangeKind
Controls the various implementations for complex multiplication and.
@ CX_Full
Implementation of complex division and multiplication using a call to runtime library functions(gener...
@ CX_Basic
Implementation of complex division and multiplication using algebraic formulas at source precision.
@ FPE_Strict
Strictly preserve the floating-point exception semantics.
@ FPE_MayTrap
Transformations do not cause new exceptions but may hide some.
@ FPE_Ignore
Assume that floating-point exceptions are masked.
virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, StringRef Str)
Callback invoked when a #pragma comment directive is read.
virtual void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name, SourceLocation StateLoc, unsigned State)
Called when an OpenCL extension is either disabled or enabled with a pragma.
virtual void PragmaDetectMismatch(SourceLocation Loc, StringRef Name, StringRef Value)
Callback invoked when a #pragma detect_mismatch directive is read.
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
ParsedAttributes - A collection of parsed attributes.
Definition ParsedAttr.h:937
ParsedAttr * addNew(IdentifierInfo *attrName, SourceRange attrRange, AttributeScopeInfo scope, ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form, SourceLocation ellipsisLoc=SourceLocation())
Add attribute with expression arguments.
Definition ParsedAttr.h:978
ParseScope - Introduces a new scope for parsing.
Definition Parser.h:396
Parser - This implements a parser for the C family of languages.
Definition Parser.h:171
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Definition Parser.cpp:85
SourceLocation getEndOfPreviousToken() const
Definition Parser.cpp:1878
ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral=false)
ParseStringLiteralExpression - This handles the various token types that form string literals,...
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
Definition Parser.h:262
Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies)
Definition Parser.cpp:56
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
Definition Parser.h:290
ExprResult ParseConstantExpression()
bool TryConsumeToken(tok::TokenKind Expected)
Definition Parser.h:270
Scope * getCurScope() const
Definition Parser.h:211
const TargetInfo & getTargetInfo() const
Definition Parser.h:205
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...
Definition Parser.h:495
const Token & getCurToken() const
Definition Parser.h:210
const LangOptions & getLangOpts() const
Definition Parser.h:204
ExprResult ParseExpression(TypoCorrectionTypeBehavior CorrectionBehavior=TypoCorrectionTypeBehavior::AllowNonTypes)
Simple precedence-based parser for binary/ternary operators.
Definition ParseExpr.cpp:47
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
Definition Parser.h:476
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
Definition Parser.h:324
friend class BalancedDelimiterTracker
Definition Parser.h:199
PragmaHandler - Instances of this interface defined to handle the various pragmas that the language f...
Definition Pragma.h:65
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void EnterToken(const Token &Tok, bool IsReinject)
Enters a token in the token stream to be lexed next.
PPCallbacks * getPPCallbacks() const
void overrideMaxTokens(unsigned Value, SourceLocation Loc)
void Lex(Token &Result)
Lex the next token for this preprocessor.
SourceRange DiscardUntilEndOfDirective()
Read and discard all tokens remaining on the current line until the tok::eod token is found.
bool LexOnOffSwitch(tok::OnOffSwitch &Result)
Lex an on-off-switch (C99 6.10.6p2) and verify that it is followed by EOD.
Definition Pragma.cpp:971
unsigned getTokenCount() const
Get the number of tokens processed so far.
const TargetInfo & getTargetInfo() const
bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value)
Parses a simple integer literal to get its numeric value.
void LexUnexpandedToken(Token &Result)
Just like Lex, but disables macro expansion of identifier tokens.
llvm::BumpPtrAllocator & getPreprocessorAllocator()
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
const LangOptions & getLangOpts() const
DiagnosticsEngine & getDiagnostics() const
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
bool LexStringLiteral(Token &Result, std::string &String, const char *DiagnosticTag, bool AllowMacroExpansion)
Lex a string literal, which may be the concatenation of multiple string literals and may even come fr...
@ CompoundStmtScope
This is a compound statement scope.
Definition Scope.h:134
@ FnScope
This indicates that the scope corresponds to a function, which means that labels are set here.
Definition Scope.h:51
@ DeclScope
This is a scope that can contain a declaration.
Definition Scope.h:63
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:854
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9289
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6675
PragmaMsStackAction
Definition Sema.h:1821
@ PSK_Push_Set
Definition Sema.h:1827
@ PSK_Reset
Definition Sema.h:1822
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
unsigned getLength() const
Definition Expr.h:1911
StringRef getString() const
Definition Expr.h:1869
unsigned getCharByteWidth() const
Definition Expr.h:1912
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
virtual bool hasStrictFP() const
Determine whether constrained floating point is supported on this target.
Definition TargetInfo.h:737
Token - This structure provides full information about a lexed token.
Definition Token.h:36
IdentifierInfo * getIdentifierInfo() const
Definition Token.h:189
void setLiteralData(const char *Ptr)
Definition Token.h:231
bool isAnyIdentifier() const
Return true if this is a raw identifier (when lexing in raw mode) or a non-keyword identifier (when l...
Definition Token.h:112
void setAnnotationEndLoc(SourceLocation L)
Definition Token.h:152
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Definition Token.h:134
void setLength(unsigned Len)
Definition Token.h:143
void setKind(tok::TokenKind K)
Definition Token.h:98
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
Definition Token.h:102
tok::TokenKind getKind() const
Definition Token.h:97
bool isOneOf(Ts... Ks) const
Definition Token.h:104
@ IsReinjected
Definition Token.h:89
void setLocation(SourceLocation L)
Definition Token.h:142
bool isNot(tok::TokenKind K) const
Definition Token.h:103
void setAnnotationValue(void *val)
Definition Token.h:240
void startToken()
Reset all flags to cleared.
Definition Token.h:179
#define bool
Definition gpuintrin.h:32
Defines the clang::TargetInfo interface.
SubjectMatchRule
A list of all the recognized kinds of attributes.
const char * getSubjectMatchRuleSpelling(SubjectMatchRule Rule)
llvm::DenseMap< int, SourceRange > ParsedSubjectMatchRuleSet
uint32_t Literal
Literals are represented as positive integers.
Definition CNFFormula.h:35
unsigned kind
All of the diagnostics that can be emitted by the frontend.
@ Ignored
Do not present this diagnostic, ignore it.
@ FixIt
Parse and apply any fixits to the source.
const Regex Rule("(.+)/(.+)\\.framework/")
bool Pop(InterpState &S, CodePtr OpPC)
Definition Interp.h:1307
const char * getKeywordSpelling(TokenKind Kind) LLVM_READNONE
Determines the spelling of simple keyword and contextual keyword tokens like 'int' and 'dynamic_cast'...
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Definition TokenKinds.h:25
OnOffSwitch
Defines the possible values of an on-off-switch (C99 6.10.6p2).
Definition TokenKinds.h:56
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...
The JSON file list parser is used to communicate input to InstallAPI.
@ PFK_Reassociate
Definition PragmaKinds.h:40
@ PFK_EvalMethod
Definition PragmaKinds.h:43
@ PFK_Exceptions
Definition PragmaKinds.h:42
@ PFK_Reciprocal
Definition PragmaKinds.h:41
@ PFK_Contract
Definition PragmaKinds.h:39
PragmaMSCommentKind
Definition PragmaKinds.h:14
@ PCK_ExeStr
Definition PragmaKinds.h:19
@ PCK_Compiler
Definition PragmaKinds.h:18
@ PCK_Linker
Definition PragmaKinds.h:16
@ PCK_Lib
Definition PragmaKinds.h:17
@ PCK_Unknown
Definition PragmaKinds.h:15
@ PCK_User
Definition PragmaKinds.h:20
@ CR_Default
PragmaOptionsAlignKind
Definition Sema.h:475
StmtResult StmtError()
Definition Ownership.h:266
const FunctionProtoType * T
MSVtorDispMode
In the Microsoft ABI, this controls the placement of virtual displacement members used to implement v...
Definition LangOptions.h:37
PragmaMSStructKind
Definition PragmaKinds.h:23
@ PMSST_ON
Definition PragmaKinds.h:25
@ PMSST_OFF
Definition PragmaKinds.h:24
PragmaFloatControlKind
Definition PragmaKinds.h:28
@ PFC_NoExcept
Definition PragmaKinds.h:33
@ PFC_NoPrecise
Definition PragmaKinds.h:31
@ PFC_Pop
Definition PragmaKinds.h:35
@ PFC_Precise
Definition PragmaKinds.h:30
@ PFC_Unknown
Definition PragmaKinds.h:29
@ PFC_Except
Definition PragmaKinds.h:32
@ PFC_Push
Definition PragmaKinds.h:34
U cast(CodeGen::Address addr)
Definition Address.h:327
@ None
The alignment was not explicit in code.
Definition ASTContext.h:146
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ Parens
New-expression has a C++98 paren-delimited initializer.
Definition ExprCXX.h:2247
ActionResult< Stmt * > StmtResult
Definition Ownership.h:250
unsigned long uint64_t
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
Loop optimization hint for loop and unroll pragmas.
Definition LoopHint.h:20
SourceRange Range
Definition LoopHint.h:22
IdentifierLoc * OptionLoc
Definition LoopHint.h:30
IdentifierLoc * StateLoc
Definition LoopHint.h:33
Expr * ValueExpr
Definition LoopHint.h:35
IdentifierLoc * PragmaNameLoc
Definition LoopHint.h:26
Describes how and where the pragma was introduced.
Definition Pragma.h:51
SourceLocation Loc
Definition Pragma.h:53
ArrayRef< Token > Toks
Definition Token.h:352
PragmaMsStackAction Action
Definition Sema.h:1832