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