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