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