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